@@ -59,9 +59,7 @@ class FunctionRef;
59
59
60
60
template <typename Ret, typename ... Params>
61
61
class FunctionRef <Ret(Params...)> {
62
- Ret (*callback_)(const void * memory, Params... params) = nullptr ;
63
62
union Storage {
64
- void * callable;
65
63
Ret (*function)(Params...);
66
64
} storage_;
67
65
@@ -70,57 +68,18 @@ class FunctionRef<Ret(Params...)> {
70
68
explicit FunctionRef (std::nullptr_t ) {}
71
69
72
70
/* *
73
- * Case 1: A callable object passed by lvalue reference.
74
- * Taking rvalue reference is error prone because the object will be always
75
- * be destroyed immediately.
76
- */
77
- template <
78
- typename Callable,
79
- // This is not the copy-constructor.
80
- typename std::enable_if<
81
- !std::is_same<remove_cvref_t <Callable>, FunctionRef>::value,
82
- int32_t >::type = 0 ,
83
- // Avoid lvalue reference to non-capturing lambda.
84
- typename std::enable_if<
85
- !std::is_convertible<Callable, Ret (*)(Params...)>::value,
86
- int32_t >::type = 0 ,
87
- // Functor must be callable and return a suitable type.
88
- // To make this container type safe, we need to ensure either:
89
- // 1. The return type is void.
90
- // 2. Or the resulting type from calling the callable is convertible to
91
- // the declared return type.
92
- typename std::enable_if<
93
- std::is_void<Ret>::value ||
94
- std::is_convertible<
95
- decltype (std::declval<Callable>()(std::declval<Params>()...)),
96
- Ret>::value,
97
- int32_t >::type = 0 >
98
- explicit FunctionRef (Callable& callable)
99
- : callback_([](const void * memory, Params... params) {
100
- auto & storage = *static_cast <const Storage*>(memory);
101
- auto & callable = *static_cast <Callable*>(storage.callable );
102
- return static_cast <Ret>(callable (std::forward<Params>(params)...));
103
- }) {
104
- storage_.callable = &callable;
105
- }
106
-
107
- /* *
108
- * Case 2: A plain function pointer.
71
+ * Case 1: A plain function pointer.
109
72
* Instead of storing an opaque pointer to underlying callable object,
110
73
* store a function pointer directly.
111
74
* Note that in the future a variant which coerces compatible function
112
75
* pointers could be implemented by erasing the storage type.
113
76
*/
114
- /* implicit */ FunctionRef(Ret (*ptr)(Params...))
115
- : callback_([](const void * memory, Params... params) {
116
- auto & storage = *static_cast <const Storage*>(memory);
117
- return storage.function (std::forward<Params>(params)...);
118
- }) {
77
+ /* implicit */ FunctionRef(Ret (*ptr)(Params...)) {
119
78
storage_.function = ptr;
120
79
}
121
80
122
81
/* *
123
- * Case 3 : Implicit conversion from lambda to FunctionRef.
82
+ * Case 2 : Implicit conversion from lambda to FunctionRef.
124
83
* A common use pattern is like:
125
84
* void foo(FunctionRef<...>) {...}
126
85
* foo([](...){...})
@@ -144,11 +103,11 @@ class FunctionRef<Ret(Params...)> {
144
103
: FunctionRef(static_cast <Ret (*)(Params...)>(function)) {}
145
104
146
105
Ret operator ()(Params... params) const {
147
- return callback_ (& storage_, std::forward<Params>(params)...);
106
+ return storage_. function ( std::forward<Params>(params)...);
148
107
}
149
108
150
109
explicit operator bool () const {
151
- return callback_ ;
110
+ return storage_. function ;
152
111
}
153
112
};
154
113
0 commit comments