1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * @author Eric Niebler (eniebler@fb.com), Sven Over (over@fb.com)
19 * Acknowledgements: Giuseppe Ottaviano (ott@fb.com)
20 */
21
22 /**
23 * @class Function
24 *
25 * @brief A polymorphic function wrapper that is not copyable and does not
26 * require the wrapped function to be copy constructible.
27 *
28 * `folly::Function` is a polymorphic function wrapper, similar to
29 * `std::function`. The template parameters of the `folly::Function` define
30 * the parameter signature of the wrapped callable, but not the specific
31 * type of the embedded callable. E.g. a `folly::Function<int(int)>`
32 * can wrap callables that return an `int` when passed an `int`. This can be a
33 * function pointer or any class object implementing one or both of
34 *
35 * int operator(int);
36 * int operator(int) const;
37 *
38 * If both are defined, the non-const one takes precedence.
39 *
40 * Unlike `std::function`, a `folly::Function` can wrap objects that are not
41 * copy constructible. As a consequence of this, `folly::Function` itself
42 * is not copyable, either.
43 *
44 * Another difference is that, unlike `std::function`, `folly::Function` treats
45 * const-ness of methods correctly. While a `std::function` allows to wrap
46 * an object that only implements a non-const `operator()` and invoke
47 * a const-reference of the `std::function`, `folly::Function` requires you to
48 * declare a function type as const in order to be able to execute it on a
49 * const-reference.
50 *
51 * For example:
52 *
53 * class Foo {
54 * public:
55 * void operator()() {
56 * // mutates the Foo object
57 * }
58 * };
59 *
60 * class Bar {
61 * std::function<void(void)> foo_; // wraps a Foo object
62 * public:
63 * void mutateFoo() const
64 * {
65 * foo_();
66 * }
67 * };
68 *
69 * Even though `mutateFoo` is a const-method, so it can only reference `foo_`
70 * as const, it is able to call the non-const `operator()` of the Foo
71 * object that is embedded in the foo_ function.
72 *
73 * `folly::Function` will not allow you to do that. You will have to decide
74 * whether you need to invoke your wrapped callable from a const reference
75 * (like in the example above), in which case it will only wrap a
76 * `operator() const`. If your functor does not implement that,
77 * compilation will fail. If you do not require to be able to invoke the
78 * wrapped function in a const context, you can wrap any functor that
79 * implements either or both of const and non-const `operator()`.
80 *
81 * The template parameter of `folly::Function`, the `FunctionType`, can be
82 * const-qualified. Be aware that the const is part of the function signature.
83 * It does not mean that the function type is a const type.
84 *
85 * using FunctionType = R(Args...);
86 * using ConstFunctionType = R(Args...) const;
87 *
88 * In this example, `FunctionType` and `ConstFunctionType` are different
89 * types. `ConstFunctionType` is not the same as `const FunctionType`.
90 * As a matter of fact, trying to use the latter should emit a compiler
91 * warning or error, because it has no defined meaning.
92 *
93 * // This will not compile:
94 * folly::Function<void(void) const> func = Foo();
95 * // because Foo does not have a member function of the form:
96 * // void operator()() const;
97 *
98 * // This will compile just fine:
99 * folly::Function<void(void)> func = Foo();
100 * // and it will wrap the existing member function:
101 * // void operator()();
102 *
103 * When should a const function type be used? As a matter of fact, you will
104 * probably not need to use const function types very often. See the following
105 * example:
106 *
107 * class Bar {
108 * folly::Function<void()> func_;
109 * folly::Function<void() const> constFunc_;
110 *
111 * void someMethod() {
112 * // Can call func_.
113 * func_();
114 * // Can call constFunc_.
115 * constFunc_();
116 * }
117 *
118 * void someConstMethod() const {
119 * // Can call constFunc_.
120 * constFunc_();
121 * // However, cannot call func_ because a non-const method cannot
122 * // be called from a const one.
123 * }
124 * };
125 *
126 * As you can see, whether the `folly::Function`'s function type should
127 * be declared const or not is identical to whether a corresponding method
128 * would be declared const or not.
129 *
130 * You only require a `folly::Function` to hold a const function type, if you
131 * intend to invoke it from within a const context. This is to ensure that
132 * you cannot mutate its inner state when calling in a const context.
133 *
134 * This is how the const/non-const choice relates to lambda functions:
135 *
136 * // Non-mutable lambdas: can be stored in a non-const...
137 * folly::Function<void(int)> print_number =
138 * [] (int number) { std::cout << number << std::endl; };
139 *
140 * // ...as well as in a const folly::Function
141 * folly::Function<void(int) const> print_number_const =
142 * [] (int number) { std::cout << number << std::endl; };
143 *
144 * // Mutable lambda: can only be stored in a non-const folly::Function:
145 * int number = 0;
146 * folly::Function<void()> print_number =
147 * [number] () mutable { std::cout << ++number << std::endl; };
148 * // Trying to store the above mutable lambda in a
149 * // `folly::Function<void() const>` would lead to a compiler error:
150 * // error: no viable conversion from '(lambda at ...)' to
151 * // 'folly::Function<void () const>'
152 *
153 * Casting between const and non-const `folly::Function`s:
154 * conversion from const to non-const signatures happens implicitly. Any
155 * function that takes a `folly::Function<R(Args...)>` can be passed
156 * a `folly::Function<R(Args...) const>` without explicit conversion.
157 * This is safe, because casting from const to non-const only entails giving
158 * up the ability to invoke the function from a const context.
159 * Casting from a non-const to a const signature is potentially dangerous,
160 * as it means that a function that may change its inner state when invoked
161 * is made possible to call from a const context. Therefore this cast does
162 * not happen implicitly. The function `folly::constCastFunction` can
163 * be used to perform the cast.
164 *
165 * // Mutable lambda: can only be stored in a non-const folly::Function:
166 * int number = 0;
167 * folly::Function<void()> print_number =
168 * [number] () mutable { std::cout << ++number << std::endl; };
169 *
170 * // const-cast to a const folly::Function:
171 * folly::Function<void() const> print_number_const =
172 * constCastFunction(std::move(print_number));
173 *
174 * When to use const function types?
175 * Generally, only when you need them. When you use a `folly::Function` as a
176 * member of a struct or class, only use a const function signature when you
177 * need to invoke the function from const context.
178 * When passing a `folly::Function` to a function, the function should accept
179 * a non-const `folly::Function` whenever possible, i.e. when it does not
180 * need to pass on or store a const `folly::Function`. This is the least
181 * possible constraint: you can always pass a const `folly::Function` when
182 * the function accepts a non-const one.
183 *
184 * How does the const behaviour compare to `std::function`?
185 * `std::function` can wrap object with non-const invocation behaviour but
186 * exposes them as const. The equivalent behaviour can be achieved with
187 * `folly::Function` like so:
188 *
189 * std::function<void(void)> stdfunc = someCallable;
190 *
191 * folly::Function<void(void) const> uniqfunc = constCastFunction(
192 * folly::Function<void(void)>(someCallable)
193 * );
194 *
195 * You need to wrap the callable first in a non-const `folly::Function` to
196 * select a non-const invoke operator (or the const one if no non-const one is
197 * present), and then move it into a const `folly::Function` using
198 * `constCastFunction`.
199 * The name of `constCastFunction` should warn you that something
200 * potentially dangerous is happening. As a matter of fact, using
201 * `std::function` always involves this potentially dangerous aspect, which
202 * is why it is not considered fully const-safe or even const-correct.
203 * However, in most of the cases you will not need the dangerous aspect at all.
204 * Either you do not require invocation of the function from a const context,
205 * in which case you do not need to use `constCastFunction` and just
206 * use the inner `folly::Function` in the example above, i.e. just use a
207 * non-const `folly::Function`. Or, you may need invocation from const, but
208 * the callable you are wrapping does not mutate its state (e.g. it is a class
209 * object and implements `operator() const`, or it is a normal,
210 * non-mutable lambda), in which case you can wrap the callable in a const
211 * `folly::Function` directly, without using `constCastFunction`.
212 * Only if you require invocation from a const context of a callable that
213 * may mutate itself when invoked you have to go through the above procedure.
214 * However, in that case what you do is potentially dangerous and requires
215 * the equivalent of a `const_cast`, hence you need to call
216 * `constCastFunction`.
217 */
218
219 #pragma once
220
221 #include <functional>
222 #include <memory>
223 #include <new>
224 #include <type_traits>
225 #include <utility>
226
227 #include <folly/CppAttributes.h>
228 #include <folly/Portability.h>
229 #include <folly/Traits.h>
230 #include <folly/functional/Invoke.h>
231 #include <folly/lang/Exception.h>
232
233 namespace folly {
234
235 template <typename FunctionType>
236 class Function;
237
238 template <typename ReturnType, typename... Args>
239 Function<ReturnType(Args...) const> constCastFunction(
240 Function<ReturnType(Args...)>&&) noexcept;
241
242 #if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE
243 template <typename ReturnType, typename... Args>
244 Function<ReturnType(Args...) const noexcept> constCastFunction(
245 Function<ReturnType(Args...) noexcept>&&) noexcept;
246 #endif
247
248 namespace detail {
249 namespace function {
250
251 enum class Op { MOVE, NUKE, HEAP };
252
253 union Data {
Data()254 Data() {}
255 void* big;
256 std::aligned_storage<6 * sizeof(void*)>::type tiny;
257 };
258
259 template <typename Fun, typename = Fun*>
260 using IsSmall = Conjunction<
261 bool_constant<(sizeof(Fun) <= sizeof(Data::tiny))>,
262 std::is_nothrow_move_constructible<Fun>>;
263 using SmallTag = std::true_type;
264 using HeapTag = std::false_type;
265
266 struct CoerceTag {};
267
268 template <typename T>
269 using FunctionNullptrTest =
270 decltype(static_cast<bool>(static_cast<T const&>(T(nullptr)) == nullptr));
271
272 template <
273 typename T,
274 std::enable_if_t<!is_detected_v<FunctionNullptrTest, T>, int> = 0>
isEmptyFunction(T const &)275 constexpr bool isEmptyFunction(T const&) {
276 return false;
277 }
278 template <
279 typename T,
280 std::enable_if_t<is_detected_v<FunctionNullptrTest, T>, int> = 0>
isEmptyFunction(T const & t)281 constexpr bool isEmptyFunction(T const& t) {
282 return static_cast<bool>(t == nullptr);
283 }
284
285 template <typename F, typename... Args>
286 using CallableResult = decltype(std::declval<F>()(std::declval<Args>()...));
287
288 template <
289 typename From,
290 typename To,
291 typename = typename std::enable_if<
292 !std::is_reference<To>::value || std::is_reference<From>::value>::type>
293 using IfSafeResultImpl = decltype(void(static_cast<To>(std::declval<From>())));
294
295 #if defined(_MSC_VER)
296 // Need a workaround for MSVC to avoid the inscrutable error:
297 //
298 // folly\function.h(...) : fatal error C1001: An internal error has
299 // occurred in the compiler.
300 // (compiler file 'f:\dd\vctools\compiler\utc\src\p2\main.c', line 258)
301 // To work around this problem, try simplifying or changing the program
302 // near the locations listed above.
303 template <typename T>
304 using CallArg = T&&;
305 #else
306 template <typename T>
307 using CallArg = conditional_t<is_trivially_copyable<T>::value, T, T&&>;
308 #endif
309
310 template <typename F, typename R, typename... A>
311 class FunctionTraitsSharedProxy {
312 std::shared_ptr<Function<F>> sp_;
313
314 public:
FunctionTraitsSharedProxy(std::nullptr_t)315 explicit FunctionTraitsSharedProxy(std::nullptr_t) noexcept {}
FunctionTraitsSharedProxy(Function<F> && func)316 explicit FunctionTraitsSharedProxy(Function<F>&& func)
317 : sp_(func ? std::make_shared<Function<F>>(std::move(func))
318 : std::shared_ptr<Function<F>>()) {}
operator()319 R operator()(A&&... args) const {
320 if (!sp_) {
321 throw_exception<std::bad_function_call>();
322 }
323 return (*sp_)(static_cast<A&&>(args)...);
324 }
325
326 explicit operator bool() const noexcept { return sp_ != nullptr; }
327
328 friend bool operator==(
329 FunctionTraitsSharedProxy<F, R, A...> const& proxy,
330 std::nullptr_t) noexcept {
331 return proxy.sp_ == nullptr;
332 }
333 friend bool operator!=(
334 FunctionTraitsSharedProxy<F, R, A...> const& proxy,
335 std::nullptr_t) noexcept {
336 return proxy.sp_ != nullptr;
337 }
338
339 friend bool operator==(
340 std::nullptr_t,
341 FunctionTraitsSharedProxy<F, R, A...> const& proxy) noexcept {
342 return proxy.sp_ == nullptr;
343 }
344 friend bool operator!=(
345 std::nullptr_t,
346 FunctionTraitsSharedProxy<F, R, A...> const& proxy) noexcept {
347 return proxy.sp_ != nullptr;
348 }
349 };
350
351 template <typename FunctionType>
352 struct FunctionTraits;
353
354 template <typename ReturnType, typename... Args>
355 struct FunctionTraits<ReturnType(Args...)> {
356 using Call = ReturnType (*)(CallArg<Args>..., Data&);
357 using IsConst = std::false_type;
358 using ConstSignature = ReturnType(Args...) const;
359 using NonConstSignature = ReturnType(Args...);
360 using OtherSignature = ConstSignature;
361
362 template <typename F, typename R = CallableResult<std::decay_t<F>&, Args...>>
363 using IfSafeResult = IfSafeResultImpl<R, ReturnType>;
364
365 template <typename Fun>
366 static ReturnType callSmall(CallArg<Args>... args, Data& p) {
367 auto& fn = *static_cast<Fun*>(static_cast<void*>(&p.tiny));
368 #if __cpp_if_constexpr >= 201606L
369 if constexpr (std::is_void<ReturnType>::value) {
370 fn(static_cast<Args&&>(args)...);
371 } else {
372 return fn(static_cast<Args&&>(args)...);
373 }
374 #else
375 return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
376 #endif
377 }
378
379 template <typename Fun>
380 static ReturnType callBig(CallArg<Args>... args, Data& p) {
381 auto& fn = *static_cast<Fun*>(p.big);
382 #if __cpp_if_constexpr >= 201606L
383 if constexpr (std::is_void<ReturnType>::value) {
384 fn(static_cast<Args&&>(args)...);
385 } else {
386 return fn(static_cast<Args&&>(args)...);
387 }
388 #else
389 return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
390 #endif
391 }
392
393 static ReturnType uninitCall(CallArg<Args>..., Data&) {
394 throw_exception<std::bad_function_call>();
395 }
396
397 ReturnType operator()(Args... args) {
398 auto& fn = *static_cast<Function<NonConstSignature>*>(this);
399 return fn.call_(static_cast<Args&&>(args)..., fn.data_);
400 }
401
402 using SharedProxy =
403 FunctionTraitsSharedProxy<NonConstSignature, ReturnType, Args...>;
404 };
405
406 template <typename ReturnType, typename... Args>
407 struct FunctionTraits<ReturnType(Args...) const> {
408 using Call = ReturnType (*)(CallArg<Args>..., Data&);
409 using IsConst = std::true_type;
410 using ConstSignature = ReturnType(Args...) const;
411 using NonConstSignature = ReturnType(Args...);
412 using OtherSignature = NonConstSignature;
413
414 template <
415 typename F,
416 typename R = CallableResult<const std::decay_t<F>&, Args...>>
417 using IfSafeResult = IfSafeResultImpl<R, ReturnType>;
418
419 template <typename Fun>
420 static ReturnType callSmall(CallArg<Args>... args, Data& p) {
421 auto& fn = *static_cast<const Fun*>(static_cast<void*>(&p.tiny));
422 #if __cpp_if_constexpr >= 201606L
423 if constexpr (std::is_void<ReturnType>::value) {
424 fn(static_cast<Args&&>(args)...);
425 } else {
426 return fn(static_cast<Args&&>(args)...);
427 }
428 #else
429 return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
430 #endif
431 }
432
433 template <typename Fun>
434 static ReturnType callBig(CallArg<Args>... args, Data& p) {
435 auto& fn = *static_cast<const Fun*>(p.big);
436 #if __cpp_if_constexpr >= 201606L
437 if constexpr (std::is_void<ReturnType>::value) {
438 fn(static_cast<Args&&>(args)...);
439 } else {
440 return fn(static_cast<Args&&>(args)...);
441 }
442 #else
443 return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
444 #endif
445 }
446
447 static ReturnType uninitCall(CallArg<Args>..., Data&) {
448 throw_exception<std::bad_function_call>();
449 }
450
451 ReturnType operator()(Args... args) const {
452 auto& fn = *static_cast<const Function<ConstSignature>*>(this);
453 return fn.call_(static_cast<Args&&>(args)..., fn.data_);
454 }
455
456 using SharedProxy =
457 FunctionTraitsSharedProxy<ConstSignature, ReturnType, Args...>;
458 };
459
460 #if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE
461 template <typename ReturnType, typename... Args>
462 struct FunctionTraits<ReturnType(Args...) noexcept> {
463 using Call = ReturnType (*)(CallArg<Args>..., Data&) noexcept;
464 using IsConst = std::false_type;
465 using ConstSignature = ReturnType(Args...) const noexcept;
466 using NonConstSignature = ReturnType(Args...) noexcept;
467 using OtherSignature = ConstSignature;
468
469 template <typename F, typename R = CallableResult<std::decay_t<F>&, Args...>>
470 using IfSafeResult = IfSafeResultImpl<R, ReturnType>;
471
472 template <typename Fun>
473 static ReturnType callSmall(CallArg<Args>... args, Data& p) noexcept {
474 auto& fn = *static_cast<Fun*>(static_cast<void*>(&p.tiny));
475 #if __cpp_if_constexpr >= 201606L
476 if constexpr (std::is_void<ReturnType>::value) {
477 fn(static_cast<Args&&>(args)...);
478 } else {
479 return fn(static_cast<Args&&>(args)...);
480 }
481 #else
482 return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
483 #endif
484 }
485
486 template <typename Fun>
487 static ReturnType callBig(CallArg<Args>... args, Data& p) noexcept {
488 auto& fn = *static_cast<Fun*>(p.big);
489 #if __cpp_if_constexpr >= 201606L
490 if constexpr (std::is_void<ReturnType>::value) {
491 fn(static_cast<Args&&>(args)...);
492 } else {
493 return fn(static_cast<Args&&>(args)...);
494 }
495 #else
496 return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
497 #endif
498 }
499
500 static ReturnType uninitCall(CallArg<Args>..., Data&) noexcept {
501 terminate_with<std::bad_function_call>();
502 }
503
504 ReturnType operator()(Args... args) noexcept {
505 auto& fn = *static_cast<Function<NonConstSignature>*>(this);
506 return fn.call_(static_cast<Args&&>(args)..., fn.data_);
507 }
508
509 using SharedProxy =
510 FunctionTraitsSharedProxy<NonConstSignature, ReturnType, Args...>;
511 };
512
513 template <typename ReturnType, typename... Args>
514 struct FunctionTraits<ReturnType(Args...) const noexcept> {
515 using Call = ReturnType (*)(CallArg<Args>..., Data&) noexcept;
516 using IsConst = std::true_type;
517 using ConstSignature = ReturnType(Args...) const noexcept;
518 using NonConstSignature = ReturnType(Args...) noexcept;
519 using OtherSignature = NonConstSignature;
520
521 template <
522 typename F,
523 typename R = CallableResult<const std::decay_t<F>&, Args...>>
524 using IfSafeResult = IfSafeResultImpl<R, ReturnType>;
525
526 template <typename Fun>
527 static ReturnType callSmall(CallArg<Args>... args, Data& p) noexcept {
528 auto& fn = *static_cast<const Fun*>(static_cast<void*>(&p.tiny));
529 #if __cpp_if_constexpr >= 201606L
530 if constexpr (std::is_void<ReturnType>::value) {
531 fn(static_cast<Args&&>(args)...);
532 } else {
533 return fn(static_cast<Args&&>(args)...);
534 }
535 #else
536 return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
537 #endif
538 }
539
540 template <typename Fun>
541 static ReturnType callBig(CallArg<Args>... args, Data& p) noexcept {
542 auto& fn = *static_cast<const Fun*>(p.big);
543 #if __cpp_if_constexpr >= 201606L
544 if constexpr (std::is_void<ReturnType>::value) {
545 fn(static_cast<Args&&>(args)...);
546 } else {
547 return fn(static_cast<Args&&>(args)...);
548 }
549 #else
550 return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
551 #endif
552 }
553
554 static ReturnType uninitCall(CallArg<Args>..., Data&) noexcept {
555 throw_exception<std::bad_function_call>();
556 }
557
558 ReturnType operator()(Args... args) const noexcept {
559 auto& fn = *static_cast<const Function<ConstSignature>*>(this);
560 return fn.call_(static_cast<Args&&>(args)..., fn.data_);
561 }
562
563 using SharedProxy =
564 FunctionTraitsSharedProxy<ConstSignature, ReturnType, Args...>;
565 };
566 #endif
567
568 template <typename Fun>
569 std::size_t execSmall(Op o, Data* src, Data* dst) {
570 switch (o) {
571 case Op::MOVE:
572 ::new (static_cast<void*>(&dst->tiny))
573 Fun(std::move(*static_cast<Fun*>(static_cast<void*>(&src->tiny))));
574 FOLLY_FALLTHROUGH;
575 case Op::NUKE:
576 static_cast<Fun*>(static_cast<void*>(&src->tiny))->~Fun();
577 break;
578 case Op::HEAP:
579 break;
580 }
581 return 0U;
582 }
583
584 template <typename Fun>
585 std::size_t execBig(Op o, Data* src, Data* dst) {
586 switch (o) {
587 case Op::MOVE:
588 dst->big = src->big;
589 src->big = nullptr;
590 break;
591 case Op::NUKE:
592 delete static_cast<Fun*>(src->big);
593 break;
594 case Op::HEAP:
595 break;
596 }
597 return sizeof(Fun);
598 }
599
600 } // namespace function
601 } // namespace detail
602
603 template <typename FunctionType>
604 class Function final : private detail::function::FunctionTraits<FunctionType> {
605 // These utility types are defined outside of the template to reduce
606 // the number of instantiations, and then imported in the class
607 // namespace for convenience.
608 using Data = detail::function::Data;
609 using Op = detail::function::Op;
610 using SmallTag = detail::function::SmallTag;
611 using HeapTag = detail::function::HeapTag;
612 using CoerceTag = detail::function::CoerceTag;
613
614 using Traits = detail::function::FunctionTraits<FunctionType>;
615 using Call = typename Traits::Call;
616 using Exec = std::size_t (*)(Op, Data*, Data*);
617
618 template <typename Fun>
619 using IsSmall = detail::function::IsSmall<Fun>;
620
621 // The `data_` member is mutable to allow `constCastFunction` to work without
622 // invoking undefined behavior. Const-correctness is only violated when
623 // `FunctionType` is a const function type (e.g., `int() const`) and `*this`
624 // is the result of calling `constCastFunction`.
625 mutable Data data_{};
626 Call call_{&Traits::uninitCall};
627 Exec exec_{nullptr};
628
629 std::size_t exec(Op o, Data* src, Data* dst) const {
630 if (!exec_) {
631 return 0U;
632 }
633 return exec_(o, src, dst);
634 }
635
636 friend Traits;
637 friend Function<typename Traits::ConstSignature> folly::constCastFunction<>(
638 Function<typename Traits::NonConstSignature>&&) noexcept;
639 friend class Function<typename Traits::OtherSignature>;
640
641 template <typename Fun>
642 Function(Fun&& fun, SmallTag) noexcept {
643 using FunT = typename std::decay<Fun>::type;
644 if (!detail::function::isEmptyFunction(fun)) {
645 ::new (static_cast<void*>(&data_.tiny)) FunT(static_cast<Fun&&>(fun));
646 call_ = &Traits::template callSmall<FunT>;
647 exec_ = &detail::function::execSmall<FunT>;
648 }
649 }
650
651 template <typename Fun>
652 Function(Fun&& fun, HeapTag) {
653 using FunT = typename std::decay<Fun>::type;
654 if (!detail::function::isEmptyFunction(fun)) {
655 data_.big = new FunT(static_cast<Fun&&>(fun));
656 call_ = &Traits::template callBig<FunT>;
657 exec_ = &detail::function::execBig<FunT>;
658 }
659 }
660
661 template <typename Signature>
662 Function(Function<Signature>&& that, CoerceTag)
663 : Function(static_cast<Function<Signature>&&>(that), HeapTag{}) {}
664
665 Function(Function<typename Traits::OtherSignature>&& that, CoerceTag) noexcept
666 : call_(that.call_), exec_(that.exec_) {
667 that.call_ = &Traits::uninitCall;
668 that.exec_ = nullptr;
669 exec(Op::MOVE, &that.data_, &data_);
670 }
671
672 public:
673 /**
674 * Default constructor. Constructs an empty Function.
675 */
676 Function() = default;
677
678 // not copyable
679 Function(const Function&) = delete;
680
681 #ifdef __OBJC__
682 // Make sure Objective C blocks are copied
683 template <class ReturnType, class... Args>
684 /*implicit*/ Function(ReturnType (^objCBlock)(Args... args))
685 : Function([blockCopy = (ReturnType(^)(Args...))[objCBlock copy]](
686 Args... args) { return blockCopy(args...); }){};
687 #endif
688
689 /**
690 * Move constructor
691 */
692 Function(Function&& that) noexcept : call_(that.call_), exec_(that.exec_) {
693 // that must be uninitialized before exec() call in the case of self move
694 that.call_ = &Traits::uninitCall;
695 that.exec_ = nullptr;
696 exec(Op::MOVE, &that.data_, &data_);
697 }
698
699 /**
700 * Constructs an empty `Function`.
701 */
702 /* implicit */ Function(std::nullptr_t) noexcept {}
703
704 /**
705 * Constructs a new `Function` from any callable object that is _not_ a
706 * `folly::Function`. This handles function pointers, pointers to static
707 * member functions, `std::reference_wrapper` objects, `std::function`
708 * objects, and arbitrary objects that implement `operator()` if the parameter
709 * signature matches (i.e. it returns an object convertible to `R` when called
710 * with `Args...`).
711 *
712 * \note `typename Traits::template IfSafeResult<Fun>` prevents this overload
713 * from being selected by overload resolution when `fun` is not a compatible
714 * function.
715 *
716 * \note The noexcept requires some explanation. `IsSmall` is true when the
717 * decayed type fits within the internal buffer and is noexcept-movable. But
718 * this ctor might copy, not move. What we need here, if this ctor does a
719 * copy, is that this ctor be noexcept when the copy is noexcept. That is not
720 * checked in `IsSmall`, and shouldn't be, because once the `Function` is
721 * constructed, the contained object is never copied. This check is for this
722 * ctor only, in the case that this ctor does a copy.
723 */
724 template <
725 typename Fun,
726 typename =
727 std::enable_if_t<!detail::is_similar_instantiation_v<Function, Fun>>,
728 typename = typename Traits::template IfSafeResult<Fun>>
729 /* implicit */ Function(Fun fun) noexcept(
730 IsSmall<Fun>::value&& noexcept(Fun(std::declval<Fun>())))
731 : Function(std::move(fun), IsSmall<Fun>{}) {}
732
733 /**
734 * For move-constructing from a `folly::Function<X(Ys...) [const?]>`.
735 * For a `Function` with a `const` function type, the object must be
736 * callable from a `const`-reference, i.e. implement `operator() const`.
737 * For a `Function` with a non-`const` function type, the object will
738 * be called from a non-const reference, which means that it will execute
739 * a non-const `operator()` if it is defined, and falls back to
740 * `operator() const` otherwise.
741 */
742 template <
743 typename Signature,
744 typename = typename Traits::template IfSafeResult<Function<Signature>>>
745 Function(Function<Signature>&& that) noexcept(
746 noexcept(Function(std::move(that), CoerceTag{})))
747 : Function(std::move(that), CoerceTag{}) {}
748
749 /**
750 * If `ptr` is null, constructs an empty `Function`. Otherwise,
751 * this constructor is equivalent to `Function(std::mem_fn(ptr))`.
752 */
753 template <
754 typename Member,
755 typename Class,
756 // Prevent this overload from being selected when `ptr` is not a
757 // compatible member function pointer.
758 typename = decltype(Function(std::mem_fn((Member Class::*)0)))>
759 /* implicit */ Function(Member Class::*ptr) noexcept {
760 if (ptr) {
761 *this = std::mem_fn(ptr);
762 }
763 }
764
765 ~Function() { exec(Op::NUKE, &data_, nullptr); }
766
767 Function& operator=(const Function&) = delete;
768
769 #ifdef __OBJC__
770 // Make sure Objective C blocks are copied
771 template <class ReturnType, class... Args>
772 /* implicit */ Function& operator=(ReturnType (^objCBlock)(Args... args)) {
773 (*this) = [blockCopy = (ReturnType(^)(Args...))[objCBlock copy]](
774 Args... args) { return blockCopy(args...); };
775 return *this;
776 }
777 #endif
778
779 /**
780 * Move assignment operator
781 *
782 * \note Leaves `that` in a valid but unspecified state. If `&that == this`
783 * then `*this` is left in a valid but unspecified state.
784 */
785 Function& operator=(Function&& that) noexcept {
786 // Q: Why is it safe to destroy and reconstruct this object in place?
787 // A: Two reasons: First, `Function` is a final class, so in doing this
788 // we aren't slicing off any derived parts. And second, the move
789 // operation is guaranteed not to throw so we always leave the object
790 // in a valid state.
791 // In the case of self-move (this == &that), this leaves the object in
792 // a default-constructed state. First the object is destroyed, then we
793 // pass the destroyed object to the move constructor. The first thing the
794 // move constructor does is default-construct the object. That object is
795 // "moved" into itself, which is a no-op for a default-constructed Function.
796 this->~Function();
797 ::new (this) Function(std::move(that));
798 return *this;
799 }
800
801 /**
802 * Assigns a callable object to this `Function`. If the operation fails,
803 * `*this` is left unmodified.
804 *
805 * \note `typename = decltype(Function(std::declval<Fun>()))` prevents this
806 * overload from being selected by overload resolution when `fun` is not a
807 * compatible function.
808 */
809 template <typename Fun, typename = decltype(Function(std::declval<Fun>()))>
810 Function& operator=(Fun fun) noexcept(
811 noexcept(/* implicit */ Function(std::declval<Fun>()))) {
812 // Doing this in place is more efficient when we can do so safely.
813 if (noexcept(/* implicit */ Function(std::declval<Fun>()))) {
814 // Q: Why is is safe to destroy and reconstruct this object in place?
815 // A: See the explanation in the move assignment operator.
816 this->~Function();
817 ::new (this) Function(std::move(fun));
818 } else {
819 // Construct a temporary and (nothrow) swap.
820 Function(std::move(fun)).swap(*this);
821 }
822 return *this;
823 }
824
825 /**
826 * For assigning from a `Function<X(Ys..) [const?]>`.
827 */
828 template <
829 typename Signature,
830 typename = typename Traits::template IfSafeResult<Function<Signature>>>
831 Function& operator=(Function<Signature>&& that) noexcept(
832 noexcept(Function(std::move(that)))) {
833 return (*this = Function(std::move(that)));
834 }
835
836 /**
837 * Clears this `Function`.
838 */
839 Function& operator=(std::nullptr_t) noexcept { return (*this = Function()); }
840
841 /**
842 * If `ptr` is null, clears this `Function`. Otherwise, this assignment
843 * operator is equivalent to `*this = std::mem_fn(ptr)`.
844 */
845 template <typename Member, typename Class>
846 auto operator=(Member Class::*ptr) noexcept
847 // Prevent this overload from being selected when `ptr` is not a
848 // compatible member function pointer.
849 -> decltype(operator=(std::mem_fn(ptr))) {
850 return ptr ? (*this = std::mem_fn(ptr)) : (*this = Function());
851 }
852
853 /**
854 * Call the wrapped callable object with the specified arguments.
855 */
856 using Traits::operator();
857
858 /**
859 * Exchanges the callable objects of `*this` and `that`.
860 */
861 void swap(Function& that) noexcept { std::swap(*this, that); }
862
863 /**
864 * Returns `true` if this `Function` contains a callable, i.e. is
865 * non-empty.
866 */
867 explicit operator bool() const noexcept { return exec_ != nullptr; }
868
869 /**
870 * Returns the size of the allocation made to store the callable on the
871 * heap. If `0` is returned, there has been no additional memory
872 * allocation because the callable is stored within the `Function` object.
873 */
874 std::size_t heapAllocatedMemory() const noexcept {
875 return exec(Op::HEAP, nullptr, nullptr);
876 }
877
878 using typename Traits::SharedProxy;
879
880 /**
881 * Move this `Function` into a copyable callable object, of which all copies
882 * share the state.
883 */
884 SharedProxy asSharedProxy() && { return SharedProxy{std::move(*this)}; }
885
886 /**
887 * Construct a `std::function` by moving in the contents of this `Function`.
888 * Note that the returned `std::function` will share its state (i.e. captured
889 * data) across all copies you make of it, so be very careful when copying.
890 */
891 std::function<typename Traits::NonConstSignature> asStdFunction() && {
892 return std::move(*this).asSharedProxy();
893 }
894 };
895
896 template <typename FunctionType>
897 void swap(Function<FunctionType>& lhs, Function<FunctionType>& rhs) noexcept {
898 lhs.swap(rhs);
899 }
900
901 template <typename FunctionType>
902 bool operator==(const Function<FunctionType>& fn, std::nullptr_t) {
903 return !fn;
904 }
905
906 template <typename FunctionType>
907 bool operator==(std::nullptr_t, const Function<FunctionType>& fn) {
908 return !fn;
909 }
910
911 template <typename FunctionType>
912 bool operator!=(const Function<FunctionType>& fn, std::nullptr_t) {
913 return !(fn == nullptr);
914 }
915
916 template <typename FunctionType>
917 bool operator!=(std::nullptr_t, const Function<FunctionType>& fn) {
918 return !(nullptr == fn);
919 }
920
921 /**
922 * NOTE: See detailed note about `constCastFunction` at the top of the file.
923 * This is potentially dangerous and requires the equivalent of a `const_cast`.
924 */
925 template <typename ReturnType, typename... Args>
926 Function<ReturnType(Args...) const> constCastFunction(
927 Function<ReturnType(Args...)>&& that) noexcept {
928 return Function<ReturnType(Args...) const>{
929 std::move(that), detail::function::CoerceTag{}};
930 }
931
932 template <typename ReturnType, typename... Args>
933 Function<ReturnType(Args...) const> constCastFunction(
934 Function<ReturnType(Args...) const>&& that) noexcept {
935 return std::move(that);
936 }
937
938 #if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE
939 template <typename ReturnType, typename... Args>
940 Function<ReturnType(Args...) const noexcept> constCastFunction(
941 Function<ReturnType(Args...) noexcept>&& that) noexcept {
942 return Function<ReturnType(Args...) const noexcept>{
943 std::move(that), detail::function::CoerceTag{}};
944 }
945
946 template <typename ReturnType, typename... Args>
947 Function<ReturnType(Args...) const noexcept> constCastFunction(
948 Function<ReturnType(Args...) const noexcept>&& that) noexcept {
949 return std::move(that);
950 }
951 #endif
952
953 /**
954 * @class FunctionRef
955 *
956 * @brief A reference wrapper for callable objects
957 *
958 * FunctionRef is similar to std::reference_wrapper, but the template parameter
959 * is the function signature type rather than the type of the referenced object.
960 * A folly::FunctionRef is cheap to construct as it contains only a pointer to
961 * the referenced callable and a pointer to a function which invokes the
962 * callable.
963 *
964 * The user of FunctionRef must be aware of the reference semantics: storing a
965 * copy of a FunctionRef is potentially dangerous and should be avoided unless
966 * the referenced object definitely outlives the FunctionRef object. Thus any
967 * function that accepts a FunctionRef parameter should only use it to invoke
968 * the referenced function and not store a copy of it. Knowing that FunctionRef
969 * itself has reference semantics, it is generally okay to use it to reference
970 * lambdas that capture by reference.
971 */
972
973 template <typename FunctionType>
974 class FunctionRef;
975
976 template <typename ReturnType, typename... Args>
977 class FunctionRef<ReturnType(Args...)> final {
978 template <typename Arg>
979 using CallArg = detail::function::CallArg<Arg>;
980
981 using Call = ReturnType (*)(CallArg<Args>..., void*);
982
983 static ReturnType uninitCall(CallArg<Args>..., void*) {
984 throw_exception<std::bad_function_call>();
985 }
986
987 template <
988 typename Fun,
989 std::enable_if_t<!std::is_pointer<Fun>::value, int> = 0>
990 static ReturnType call(CallArg<Args>... args, void* object) {
991 using Pointer = std::add_pointer_t<Fun>;
992 return static_cast<ReturnType>(invoke(
993 static_cast<Fun&&>(*static_cast<Pointer>(object)),
994 static_cast<Args&&>(args)...));
995 }
996 template <
997 typename Fun,
998 std::enable_if_t<std::is_pointer<Fun>::value, int> = 0>
999 static ReturnType call(CallArg<Args>... args, void* object) {
1000 return static_cast<ReturnType>(
1001 invoke(reinterpret_cast<Fun>(object), static_cast<Args&&>(args)...));
1002 }
1003
1004 void* object_{nullptr};
1005 Call call_{&FunctionRef::uninitCall};
1006
1007 public:
1008 /**
1009 * Default constructor. Constructs an empty FunctionRef.
1010 *
1011 * Invoking it will throw std::bad_function_call.
1012 */
1013 constexpr FunctionRef() = default;
1014
1015 /**
1016 * Like default constructor. Constructs an empty FunctionRef.
1017 *
1018 * Invoking it will throw std::bad_function_call.
1019 */
1020 constexpr explicit FunctionRef(std::nullptr_t) noexcept {}
1021
1022 /**
1023 * Construct a FunctionRef from a reference to a callable object. If the
1024 * callable is considered to be an empty callable, the FunctionRef will be
1025 * empty.
1026 */
1027 template <
1028 typename Fun,
1029 std::enable_if_t<
1030 Conjunction<
1031 Negation<std::is_same<FunctionRef, std::decay_t<Fun>>>,
1032 is_invocable_r<ReturnType, Fun&&, Args&&...>>::value,
1033 int> = 0>
1034 constexpr /* implicit */ FunctionRef(Fun&& fun) noexcept {
1035 // `Fun` may be a const type, in which case we have to do a const_cast
1036 // to store the address in a `void*`. This is safe because the `void*`
1037 // will be cast back to `Fun*` (which is a const pointer whenever `Fun`
1038 // is a const type) inside `FunctionRef::call`
1039 auto& ref = fun; // work around forwarding lint advice
1040 if (!detail::function::isEmptyFunction(ref)) {
1041 auto ptr = std::addressof(ref);
1042 object_ = const_cast<void*>(static_cast<void const*>(ptr));
1043 call_ = &FunctionRef::template call<Fun>;
1044 }
1045 }
1046
1047 /**
1048 * Constructs a FunctionRef from a pointer to a function. If the
1049 * pointer is nullptr, the FunctionRef will be empty.
1050 */
1051 template <
1052 typename Fun,
1053 std::enable_if_t<std::is_function<Fun>::value, int> = 0,
1054 std::enable_if_t<is_invocable_r_v<ReturnType, Fun&, Args&&...>, int> = 0>
1055 constexpr /* implicit */ FunctionRef(Fun* fun) noexcept {
1056 if (fun) {
1057 object_ = const_cast<void*>(reinterpret_cast<void const*>(fun));
1058 call_ = &FunctionRef::template call<Fun*>;
1059 }
1060 }
1061
1062 ReturnType operator()(Args... args) const {
1063 return call_(static_cast<Args&&>(args)..., object_);
1064 }
1065
1066 constexpr explicit operator bool() const noexcept { return object_; }
1067
1068 constexpr friend bool operator==(
1069 FunctionRef<ReturnType(Args...)> ref, std::nullptr_t) noexcept {
1070 return ref.object_ == nullptr;
1071 }
1072 constexpr friend bool operator!=(
1073 FunctionRef<ReturnType(Args...)> ref, std::nullptr_t) noexcept {
1074 return ref.object_ != nullptr;
1075 }
1076
1077 constexpr friend bool operator==(
1078 std::nullptr_t, FunctionRef<ReturnType(Args...)> ref) noexcept {
1079 return ref.object_ == nullptr;
1080 }
1081 constexpr friend bool operator!=(
1082 std::nullptr_t, FunctionRef<ReturnType(Args...)> ref) noexcept {
1083 return ref.object_ != nullptr;
1084 }
1085 };
1086
1087 } // namespace folly
1088