1 // Copyright 2019 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
16 #define ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
17
18 #include <cassert>
19 #include <functional>
20 #include <type_traits>
21
22 #include "absl/base/internal/invoke.h"
23 #include "absl/meta/type_traits.h"
24
25 namespace absl {
26 ABSL_NAMESPACE_BEGIN
27 namespace functional_internal {
28
29 // Like a void* that can handle function pointers as well. The standard does not
30 // allow function pointers to round-trip through void*, but void(*)() is fine.
31 //
32 // Note: It's important that this class remains trivial and is the same size as
33 // a pointer, since this allows the compiler to perform tail-call optimizations
34 // when the underlying function is a callable object with a matching signature.
35 union VoidPtr {
36 const void* obj;
37 void (*fun)();
38 };
39
40 // Chooses the best type for passing T as an argument.
41 // Attempt to be close to SystemV AMD64 ABI. Objects with trivial copy ctor are
42 // passed by value.
43 template <typename T>
PassByValue()44 constexpr bool PassByValue() {
45 return !std::is_lvalue_reference<T>::value &&
46 absl::is_trivially_copy_constructible<T>::value &&
47 absl::is_trivially_copy_assignable<
48 typename std::remove_cv<T>::type>::value &&
49 std::is_trivially_destructible<T>::value &&
50 sizeof(T) <= 2 * sizeof(void*);
51 }
52
53 template <typename T>
54 struct ForwardT : std::conditional<PassByValue<T>(), T, T&&> {};
55
56 // An Invoker takes a pointer to the type-erased invokable object, followed by
57 // the arguments that the invokable object expects.
58 //
59 // Note: The order of arguments here is an optimization, since member functions
60 // have an implicit "this" pointer as their first argument, putting VoidPtr
61 // first allows the compiler to perform tail-call optimization in many cases.
62 template <typename R, typename... Args>
63 using Invoker = R (*)(VoidPtr, typename ForwardT<Args>::type...);
64
65 //
66 // InvokeObject and InvokeFunction provide static "Invoke" functions that can be
67 // used as Invokers for objects or functions respectively.
68 //
69 // static_cast<R> handles the case the return type is void.
70 template <typename Obj, typename R, typename... Args>
InvokeObject(VoidPtr ptr,typename ForwardT<Args>::type...args)71 R InvokeObject(VoidPtr ptr, typename ForwardT<Args>::type... args) {
72 auto o = static_cast<const Obj*>(ptr.obj);
73 return static_cast<R>(
74 absl::base_internal::Invoke(*o, std::forward<Args>(args)...));
75 }
76
77 template <typename Fun, typename R, typename... Args>
InvokeFunction(VoidPtr ptr,typename ForwardT<Args>::type...args)78 R InvokeFunction(VoidPtr ptr, typename ForwardT<Args>::type... args) {
79 auto f = reinterpret_cast<Fun>(ptr.fun);
80 return static_cast<R>(
81 absl::base_internal::Invoke(f, std::forward<Args>(args)...));
82 }
83
84 template <typename Sig>
AssertNonNull(const std::function<Sig> & f)85 void AssertNonNull(const std::function<Sig>& f) {
86 assert(f != nullptr);
87 (void)f;
88 }
89
90 template <typename F>
AssertNonNull(const F &)91 void AssertNonNull(const F&) {}
92
93 template <typename F, typename C>
AssertNonNull(F C::* f)94 void AssertNonNull(F C::*f) {
95 assert(f != nullptr);
96 (void)f;
97 }
98
99 template <bool C>
100 using EnableIf = typename ::std::enable_if<C, int>::type;
101
102 } // namespace functional_internal
103 ABSL_NAMESPACE_END
104 } // namespace absl
105
106 #endif // ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
107