Function::asStdFunction()
[folly.git] / folly / Function.h
1 /*
2  * Copyright 2016 Facebook, Inc.
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  * @class Function
19  *
20  * @brief A polymorphic function wrapper that is not copyable and does not
21  *    require the wrapped function to be copy constructible.
22  *
23  * `folly::Function` is a polymorphic function wrapper, similar to
24  * `std::function`. The template parameters of the `folly::Function` define
25  * the parameter signature of the wrapped callable, but not the specific
26  * type of the embedded callable. E.g. a `folly::Function<int(int)>`
27  * can wrap callables that return an `int` when passed an `int`. This can be a
28  * function pointer or any class object implementing one or both of
29  *
30  *     int operator(int);
31  *     int operator(int) const;
32  *
33  * If both are defined, the non-const one takes precedence.
34  *
35  * Unlike `std::function`, a `folly::Function` can wrap objects that are not
36  * copy constructible. As a consequence of this, `folly::Function` itself
37  * is not copyable, either.
38  *
39  * Another difference is that, unlike `std::function`, `folly::Function` treats
40  * const-ness of methods correctly. While a `std::function` allows to wrap
41  * an object that only implements a non-const `operator()` and invoke
42  * a const-reference of the `std::function`, `folly::Function` requires you to
43  * declare a function type as const in order to be able to execute it on a
44  * const-reference.
45  *
46  * For example:
47  *
48  *     class Foo {
49  *      public:
50  *       void operator()() {
51  *         // mutates the Foo object
52  *       }
53  *     };
54  *
55  *     class Bar {
56  *       std::function<void(void)> foo_; // wraps a Foo object
57  *      public:
58  *       void mutateFoo() const
59  *       {
60  *         foo_();
61  *       }
62  *     };
63  *
64  * Even though `mutateFoo` is a const-method, so it can only reference `foo_`
65  * as const, it is able to call the non-const `operator()` of the Foo
66  * object that is embedded in the foo_ function.
67  *
68  * `folly::Function` will not allow you to do that. You will have to decide
69  * whether you need to invoke your wrapped callable from a const reference
70  * (like in the example above), in which case it will only wrap a
71  * `operator() const`. If your functor does not implement that,
72  * compilation will fail. If you do not require to be able to invoke the
73  * wrapped function in a const context, you can wrap any functor that
74  * implements either or both of const and non-const `operator()`.
75  *
76  * The first (and usually only specified) template parameter of
77  * `folly::Function`, the `FunctionType`, can be const-qualified. Be aware
78  * that the const is part of the function signature. It does not mean that
79  * the function type is a const type.
80  *
81  *   using FunctionType = R(Args...);
82  *   using ConstFunctionType = R(Args...) const;
83  *
84  * In this example, `FunctionType` and `ConstFunctionType` are different
85  * types. `ConstFunctionType` is not the same as `const FunctionType`.
86  * As a matter of fact, trying to use the latter should emit a compiler
87  * warning or error, because it has no defined meaning.
88  *
89  *     // This will not compile:
90  *     folly::Function<void(void) const> func = Foo();
91  *     // because Foo does not have a member function of the form:
92  *     //   void operator()() const;
93  *
94  *     // This will compile just fine:
95  *     folly::Function<void(void)> func = Foo();
96  *     // and it will wrap the existing member function:
97  *     //   void operator()();
98  *
99  * When should a const function type be used? As a matter of fact, you will
100  * probably not need to use const function types very often. See the following
101  * example:
102  *
103  *     class Bar {
104  *       folly::Function<void()> func_;
105  *       folly::Function<void() const> constFunc_;
106  *
107  *       void someMethod() {
108  *         // Can call func_.
109  *         func_();
110  *         // Can call constFunc_.
111  *         constFunc_();
112  *       }
113  *
114  *       void someConstMethod() const {
115  *         // Can call constFunc_.
116  *         constFunc_();
117  *         // However, cannot call func_ because a non-const method cannot
118  *         // be called from a const one.
119  *       }
120  *     };
121  *
122  * As you can see, whether the `folly::Function`'s function type should
123  * be declared const or not is identical to whether a corresponding method
124  * would be declared const or not.
125  *
126  * You only require a `folly::Function` to hold a const function type, if you
127  * intend to invoke it from within a const context. This is to ensure that
128  * you cannot mutate its inner state when calling in a const context.
129  *
130  * This is how the const/non-const choice relates to lambda functions:
131  *
132  *     // Non-mutable lambdas: can be stored in a non-const...
133  *     folly::Function<void(int)> print_number =
134  *       [] (int number) { std::cout << number << std::endl; };
135  *
136  *     // ...as well as in a const folly::Function
137  *     folly::Function<void(int) const> print_number_const =
138  *       [] (int number) { std::cout << number << std::endl; };
139  *
140  *     // Mutable lambda: can only be stored in a non-const folly::Function:
141  *     int number = 0;
142  *     folly::Function<void()> print_number =
143  *       [number] () mutable { std::cout << ++number << std::endl; };
144  *     // Trying to store the above mutable lambda in a
145  *     // `folly::Function<void() const>` would lead to a compiler error:
146  *     // error: no viable conversion from '(lambda at ...)' to
147  *     // 'folly::Function<void () const>'
148  *
149  * Casting between const and non-const `folly::Function`s:
150  * conversion from const to non-const signatures happens implicitly. Any
151  * function that takes a `folly::Function<R(Args...)>` can be passed
152  * a `folly::Function<R(Args...) const>` without explicit conversion.
153  * This is safe, because casting from const to non-const only entails giving
154  * up the ability to invoke the function from a const context.
155  * Casting from a non-const to a const signature is potentially dangerous,
156  * as it means that a function that may change its inner state when invoked
157  * is made possible to call from a const context. Therefore this cast does
158  * not happen implicitly. The function `folly::constCastFunction` can
159  * be used to perform the cast.
160  *
161  *     // Mutable lambda: can only be stored in a non-const folly::Function:
162  *     int number = 0;
163  *     folly::Function<void()> print_number =
164  *       [number] () mutable { std::cout << ++number << std::endl; };
165  *
166  *     // const-cast to a const folly::Function:
167  *     folly::Function<void() const> print_number_const =
168  *       constCastFunction(std::move(print_number));
169  *
170  * When to use const function types?
171  * Generally, only when you need them. When you use a `folly::Function` as a
172  * member of a struct or class, only use a const function signature when you
173  * need to invoke the function from const context.
174  * When passing a `folly::Function` to a function, the function should accept
175  * a non-const `folly::Function` whenever possible, i.e. when it does not
176  * need to pass on or store a const `folly::Function`. This is the least
177  * possible constraint: you can always pass a const `folly::Function` when
178  * the function accepts a non-const one.
179  *
180  * How does the const behaviour compare to `std::function`?
181  * `std::function` can wrap object with non-const invokation behaviour but
182  * exposes them as const. The equivalent behaviour can be achieved with
183  * `folly::Function` like so:
184  *
185  *     std::function<void(void)> stdfunc = someCallable;
186  *
187  *     folly::Function<void(void) const> uniqfunc = constCastFunction(
188  *       folly::Function<void(void)>(someCallable)
189  *     );
190  *
191  * You need to wrap the callable first in a non-const `folly::Function` to
192  * select a non-const invoke operator (or the const one if no non-const one is
193  * present), and then move it into a const `folly::Function` using
194  * `constCastFunction`.
195  * The name of `constCastFunction` should warn you that something
196  * potentially dangerous is happening. As a matter of fact, using
197  * `std::function` always involves this potentially dangerous aspect, which
198  * is why it is not considered fully const-safe or even const-correct.
199  * However, in most of the cases you will not need the dangerous aspect at all.
200  * Either you do not require invokation of the function from a const context,
201  * in which case you do not need to use `constCastFunction` and just
202  * use the inner `folly::Function` in the example above, i.e. just use a
203  * non-const `folly::Function`. Or, you may need invokation from const, but
204  * the callable you are wrapping does not mutate its state (e.g. it is a class
205  * object and implements `operator() const`, or it is a normal,
206  * non-mutable lambda), in which case you can wrap the callable in a const
207  * `folly::Function` directly, without using `constCastFunction`.
208  * Only if you require invokation from a const context of a callable that
209  * may mutate itself when invoked you have to go through the above procedure.
210  * However, in that case what you do is potentially dangerous and requires
211  * the equivalent of a `const_cast`, hence you need to call
212  * `constCastFunction`.
213  *
214  * `folly::Function` also has two additional template paremeters:
215  *   * `NTM`: if set to `folly::FunctionMoveCtor::NO_THROW`, the
216  *     `folly::Function` object is guaranteed to be nothrow move constructible.
217  *     The downside is that any function object that itself is
218  *     not nothrow move constructible cannot be stored in-place in the
219  *     `folly::Function` object and will be stored on the heap instead.
220  *   * `EmbedFunctorSize`: a number of bytes that will be reserved in the
221  *     `folly::Function` object to store callable objects in-place. If you
222  *     wrap a callable object bigger than this in a `folly::Function` object,
223  *     it will be stored on the heap and the `folly::Function` object will keep
224  *     a `std::unique_ptr` to it.
225  */
226
227 #pragma once
228
229 #include <functional>
230 #include <type_traits>
231 #include <typeinfo>
232 #include <utility>
233
234 #include <folly/ScopeGuard.h>
235 #include <folly/portability/Constexpr.h>
236
237 namespace folly {
238
239 enum class FunctionMoveCtor { NO_THROW, MAY_THROW };
240
241 template <
242     typename FunctionType,
243     FunctionMoveCtor NTM = FunctionMoveCtor::NO_THROW,
244     size_t EmbedFunctorSize = (NTM == FunctionMoveCtor::NO_THROW)
245         ? sizeof(void (*)(void))
246         : sizeof(std::function<void(void)>)>
247 class Function;
248
249 } // folly
250
251 // boring predeclarations and details
252 #include "Function-pre.h"
253
254 namespace folly {
255
256 template <typename FunctionType, FunctionMoveCtor NTM, size_t EmbedFunctorSize>
257 class Function final
258     : public detail::function::FunctionTypeTraits<FunctionType>::
259           template InvokeOperator<
260               Function<FunctionType, NTM, EmbedFunctorSize>>,
261       public detail::function::MaybeUnaryOrBinaryFunction<FunctionType> {
262  private:
263   using Traits = detail::function::FunctionTypeTraits<FunctionType>;
264   static_assert(
265       Traits::SuitableForFunction::value,
266       "Function<FunctionType>: FunctionType must be of the "
267       "form 'R(Args...)' or 'R(Args...) const'");
268
269   using ThisType = Function<FunctionType, NTM, EmbedFunctorSize>;
270   using InvokeOperator = typename Traits::template InvokeOperator<ThisType>;
271
272   static constexpr bool hasNoExceptMoveCtor() noexcept {
273     return NTM == FunctionMoveCtor::NO_THROW;
274   };
275
276  public:
277   // not copyable
278   Function(Function const&) = delete;
279   Function& operator=(Function const&) = delete;
280
281   /**
282    * Default constructor. Constructs an empty Function.
283    */
284   Function() noexcept {
285     initializeEmptyExecutor();
286   }
287
288   ~Function() {
289     destroyExecutor();
290
291     static_assert(
292         kStorageSize == sizeof(*this),
293         "There is something wrong with the size of Function");
294   }
295
296   // construct/assign from Function
297   /**
298    * Move constructor
299    */
300   Function(Function&& other) noexcept(hasNoExceptMoveCtor());
301   /**
302    * Move assignment operator
303    */
304   Function& operator=(Function&& rhs) noexcept(hasNoExceptMoveCtor());
305
306   /**
307    * Construct a std::function by moving in the contents of this `Function`.
308    * Note that the returned std::function will share its state (i.e. captured
309    * data) across all copies you make of it, so be very careful when copying.
310    */
311   std::function<typename Traits::NonConstFunctionType> asStdFunction() && {
312     return detail::function::InvokeFromSharedPtr<Function>(
313         std::make_shared<Function>(std::move(*this)));
314   }
315
316   /**
317    * Constructs a `Function` by moving from one with different template
318    * parameters with regards to const-ness, no-except-movability and internal
319    * storage size.
320    */
321   template <
322       typename OtherFunctionType,
323       FunctionMoveCtor OtherNTM,
324       size_t OtherEmbedFunctorSize>
325   Function(
326       Function<OtherFunctionType, OtherNTM, OtherEmbedFunctorSize>&& other,
327       typename std::enable_if<std::is_same<
328           typename Traits::NonConstFunctionType,
329           typename detail::function::FunctionTypeTraits<
330               OtherFunctionType>::NonConstFunctionType>::value>::type* =
331           0) noexcept(OtherNTM == FunctionMoveCtor::NO_THROW &&
332           EmbedFunctorSize >= OtherEmbedFunctorSize);
333
334   /**
335    * Moves a `Function` with different template parameters with regards
336    * to const-ness, no-except-movability and internal storage size into this
337    * one.
338    */
339   template <
340       typename RhsFunctionType,
341       FunctionMoveCtor RhsNTM,
342       size_t RhsEmbedFunctorSize>
343   Function& operator=(Function<RhsFunctionType, RhsNTM, RhsEmbedFunctorSize>&&
344                           rhs) noexcept(RhsNTM == FunctionMoveCtor::NO_THROW);
345
346   /**
347    * Constructs an empty `Function`.
348    */
349   /* implicit */ Function(std::nullptr_t) noexcept : Function() {}
350
351   /**
352    * Clears this `Function`.
353    */
354   Function& operator=(std::nullptr_t) noexcept {
355     destroyExecutor();
356     initializeEmptyExecutor();
357     return *this;
358   }
359
360   /**
361    * Constructs a new `Function` from any callable object. This
362    * handles function pointers, pointers to static member functions,
363    * `std::reference_wrapper` objects, `std::function` objects, and arbitrary
364    * objects that implement `operator()` if the parameter signature
365    * matches (i.e. it returns R when called with Args...).
366    * For a `Function` with a const function type, the object must be
367    * callable from a const-reference, i.e. implement `operator() const`.
368    * For a `Function` with a non-const function type, the object will
369    * be called from a non-const reference, which means that it will execute
370    * a non-const `operator()` if it is defined, and falls back to
371    * `operator() const` otherwise
372    */
373   template <typename F>
374   /* implicit */ Function(
375       F&& f,
376       typename std::enable_if<
377           detail::function::IsCallable<F, FunctionType>::value>::type* =
378           0) noexcept(noexcept(typename std::decay<F>::
379                                    type(std::forward<F>(f)))) {
380     createExecutor(std::forward<F>(f));
381   }
382
383   /**
384    * Assigns a callable object to this `Function`.
385    */
386   template <typename F>
387   typename std::enable_if<
388       detail::function::IsCallable<F, FunctionType>::value,
389       Function&>::type
390   operator=(F&& f) noexcept(
391       noexcept(typename std::decay<F>::type(std::forward<F>(f)))) {
392     destroyExecutor();
393     SCOPE_FAIL {
394       initializeEmptyExecutor();
395     };
396     createExecutor(std::forward<F>(f));
397     return *this;
398   }
399
400   /**
401    * Exchanges the callable objects of `*this` and `other`. `other` can be
402    * a Function with different settings with regard to
403    * no-except-movability and internal storage size, but must match
404    * `*this` with regards to return type and argument types.
405    */
406   template <FunctionMoveCtor OtherNTM, size_t OtherEmbedFunctorSize>
407   void
408   swap(Function<FunctionType, OtherNTM, OtherEmbedFunctorSize>& o) noexcept(
409       hasNoExceptMoveCtor() && OtherNTM == FunctionMoveCtor::NO_THROW);
410
411   /**
412    * Returns `true` if this `Function` contains a callable, i.e. is
413    * non-empty.
414    */
415   explicit operator bool() const noexcept;
416
417   /**
418    * Returns `true` if this `Function` stores the callable on the
419    * heap. If `false` is returned, there has been no additional memory
420    * allocation and the callable is stored inside the `Function`
421    * object itself.
422    */
423   bool hasAllocatedMemory() const noexcept;
424
425   /**
426    * Returns the `type_info` (as returned by `typeid`) of the callable stored
427    * in this `Function`. Returns `typeid(void)` if empty.
428    */
429   std::type_info const& target_type() const noexcept;
430
431   /**
432    * Returns a pointer to the stored callable if its type matches `T`, and
433    * `nullptr` otherwise.
434    */
435   template <typename T>
436   T* target() noexcept;
437
438   /**
439    * Returns a const-pointer to the stored callable if its type matches `T`,
440    * and `nullptr` otherwise.
441    */
442   template <typename T>
443   const T* target() const noexcept;
444
445   /**
446    * Move out this `Function` into one with a const function type.
447    *
448    * This is a potentially dangerous operation, equivalent to a `const_cast`.
449    * This converts a `Function` with a non-const function type, i.e.
450    * one that can only be called when in the form of a non-const reference,
451    * into one that can be called in a const context. Use at your own risk!
452    */
453   Function<typename Traits::ConstFunctionType, NTM, EmbedFunctorSize>
454       castToConstFunction() && noexcept(hasNoExceptMoveCtor());
455
456   using SignatureType = FunctionType;
457   using ResultType = typename Traits::ResultType;
458   using ArgsTuple = typename Traits::ArgsTuple;
459
460  private:
461   template <class, FunctionMoveCtor, size_t>
462   friend class Function;
463
464   friend struct detail::function::FunctionTypeTraits<FunctionType>;
465
466   using ExecutorIf =
467       typename detail::function::Executors<FunctionType>::ExecutorIf;
468   using EmptyExecutor =
469       typename detail::function::Executors<FunctionType>::EmptyExecutor;
470   template <typename F, typename SelectFunctionTag>
471   using FunctorPtrExecutor = typename detail::function::Executors<
472       FunctionType>::template FunctorPtrExecutor<F, SelectFunctionTag>;
473   template <typename F, typename SelectFunctionTag>
474   using FunctorExecutor = typename detail::function::Executors<
475       FunctionType>::template FunctorExecutor<F, SelectFunctionTag>;
476
477   template <typename T>
478   T const* access() const;
479
480   template <typename T>
481   T* access();
482
483   void initializeEmptyExecutor() noexcept;
484
485   template <typename F>
486   void createExecutor(F&& f) noexcept(
487       noexcept(typename std::decay<F>::type(std::forward<F>(f))));
488
489   void destroyExecutor() noexcept;
490
491   struct MinStorageSize;
492
493   typename std::aligned_storage<MinStorageSize::value>::type data_;
494   static constexpr size_t kStorageSize = sizeof(data_);
495 };
496
497 // operator==
498 template <typename FunctionType, FunctionMoveCtor NTM, size_t EmbedFunctorSize>
499 inline bool operator==(
500     Function<FunctionType, NTM, EmbedFunctorSize> const& f,
501     std::nullptr_t) noexcept {
502   return !f;
503 }
504
505 template <typename FunctionType, FunctionMoveCtor NTM, size_t EmbedFunctorSize>
506 inline bool operator==(
507     std::nullptr_t,
508     Function<FunctionType, NTM, EmbedFunctorSize> const& f) noexcept {
509   return !f;
510 }
511
512 template <typename FunctionType, FunctionMoveCtor NTM, size_t EmbedFunctorSize>
513 inline bool operator!=(
514     Function<FunctionType, NTM, EmbedFunctorSize> const& f,
515     std::nullptr_t) noexcept {
516   return !!f;
517 }
518
519 template <typename FunctionType, FunctionMoveCtor NTM, size_t EmbedFunctorSize>
520 inline bool operator!=(
521     std::nullptr_t,
522     Function<FunctionType, NTM, EmbedFunctorSize> const& f) noexcept {
523   return !!f;
524 }
525
526 /**
527  * Cast a `Function` into one with a const function type.
528  *
529  * This is a potentially dangerous operation, equivalent to a `const_cast`.
530  * This converts a `Function` with a non-const function type, i.e.
531  * one that can only be called when in the form of a non-const reference,
532  * into one that can be called in a const context. Use at your own risk!
533  */
534 template <typename FunctionType, FunctionMoveCtor NTM, size_t EmbedFunctorSize>
535 Function<
536     typename detail::function::FunctionTypeTraits<
537         FunctionType>::ConstFunctionType,
538     NTM,
539     EmbedFunctorSize>
540 constCastFunction(Function<FunctionType, NTM, EmbedFunctorSize>&&
541                       from) noexcept(NTM == FunctionMoveCtor::NO_THROW) {
542   return std::move(from).castToConstFunction();
543 }
544
545 template <typename FunctionType, FunctionMoveCtor NOM, size_t S>
546 void swap(
547     Function<FunctionType, NOM, S>& lhs,
548     Function<FunctionType, NOM, S>& rhs) noexcept(noexcept(lhs.swap(rhs))) {
549   lhs.swap(rhs);
550 }
551
552 template <
553     typename FunctionType,
554     FunctionMoveCtor NOM1,
555     FunctionMoveCtor NOM2,
556     size_t S1,
557     size_t S2>
558 void swap(
559     Function<FunctionType, NOM1, S1>& lhs,
560     Function<FunctionType, NOM2, S2>& rhs) noexcept(noexcept(lhs.swap(rhs))) {
561   lhs.swap(rhs);
562 }
563
564 } // namespace folly
565
566 #include "Function-inl.h"