Add <new> header for placement new
[folly.git] / folly / Function-pre.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 #pragma once
18
19 // included by Function.h, do not include directly.
20
21 #include <memory>
22
23 namespace folly {
24
25 namespace detail {
26 namespace function {
27
28 struct SelectConstFunctionTag {
29   template <typename T>
30   using QualifiedPointer = T const*;
31 };
32 struct SelectNonConstFunctionTag {
33   template <typename T>
34   using QualifiedPointer = T*;
35 };
36
37 // Helper to check whether the return type of a callable matches that of
38 // a folly::Function object. Either because the former is convertible to
39 // the latter, or the latter is void (possibly cv-qualified)
40 template <typename CallableR, typename FollyFunctionR>
41 using ReturnTypeMatches = std::integral_constant<
42     bool,
43     std::is_convertible<CallableR, FollyFunctionR>::value ||
44         std::is_same<typename std::decay<FollyFunctionR>::type, void>::value>;
45
46 // Helper class to extract properties from a function type
47 template <typename T>
48 struct FunctionTypeTraits;
49
50 // FunctionTypeTraits default implementation - this only exists to suppress
51 // very long compiler errors when Function is tried to be instantiated
52 // with an unsuitable type
53 template <typename T>
54 struct FunctionTypeTraits {
55   using SuitableForFunction = std::false_type;
56
57   // The following definitions are here only to suppress long and misleading
58   // compiler errors.
59   using ResultType = void;
60   using ArgsTuple = int;
61   using ArgsRefTuple = int;
62   using NonConstFunctionType = void;
63   using ConstFunctionType = int;
64
65   template <typename X>
66   class InvokeOperator {};
67   class ExecutorMixin {};
68 };
69
70 // FunctionTypeTraits for non-const function types
71 template <typename R, typename... Args>
72 struct FunctionTypeTraits<R(Args...)> {
73   using SuitableForFunction = std::true_type;
74   using ResultType = R;
75   using ArgsTuple = std::tuple<Args...>;
76   using ArgsRefTuple = std::tuple<Args&&...>;
77   using NonConstFunctionType = R(Args...);
78   using ConstFunctionType = R(Args...) const;
79   using IsConst = std::false_type;
80   using DefaultSelectFunctionTag = SelectNonConstFunctionTag;
81   template <typename F>
82   using IsCallable =
83       ReturnTypeMatches<typename std::result_of<F&(Args...)>::type, R>;
84   template <typename T>
85   using QualifiedPointer = T*;
86   template <typename Obj>
87   using InvokeFunctionPtr = R (*)(Obj*, Args&&...);
88
89   // Function inherits from InvokeOperator<Function>. This is
90   // where Function's operator() is defined.
91   template <typename FunctionType>
92   class InvokeOperator {
93    public:
94     /**
95      * Invokes the stored callable via the invokePtr stored in the Executor.
96      *
97      * Throws std::bad_function_call if @c *this is empty.
98      */
99     ResultType operator()(Args... args) {
100       auto executor =
101           static_cast<FunctionType*>(this)
102               ->template access<typename FunctionType::ExecutorIf>();
103       return executor->invokePtr(executor, std::forward<Args>(args)...);
104     }
105   };
106
107   class ExecutorMixin;
108 };
109
110 // FunctionTypeTraits for const function types
111 template <typename R, typename... Args>
112 struct FunctionTypeTraits<R(Args...) const> {
113   using SuitableForFunction = std::true_type;
114   using ResultType = R;
115   using ArgsTuple = std::tuple<Args...>;
116   using ArgsRefTuple = std::tuple<Args&&...>;
117   using NonConstFunctionType = R(Args...);
118   using ConstFunctionType = R(Args...) const;
119   using IsConst = std::true_type;
120   using DefaultSelectFunctionTag = SelectConstFunctionTag;
121   template <typename F>
122   using IsCallable =
123       ReturnTypeMatches<typename std::result_of<F const&(Args...)>::type, R>;
124   template <typename T>
125   using QualifiedPointer = T const*;
126   template <typename Obj>
127   using InvokeFunctionPtr = R (*)(Obj const*, Args&&...);
128
129   // Function inherits from InvokeOperator<Function>. This is
130   // where Function's operator() is defined.
131   template <typename FunctionType>
132   class InvokeOperator {
133    public:
134     /**
135      * Invokes the stored callable via the invokePtr stored in the Executor.
136      *
137      * Throws std::bad_function_call if @c *this is empty.
138      */
139     ResultType operator()(Args... args) const {
140       auto executor =
141           static_cast<FunctionType const*>(this)
142               ->template access<typename FunctionType::ExecutorIf>();
143       return executor->invokePtr(executor, std::forward<Args>(args)...);
144     }
145   };
146
147   class ExecutorMixin;
148 };
149
150 // Helper template for checking if a type T is a Function with the same
151 // function type as OtherFunctionType (except for const-ness which may differ)
152 template <typename T, typename OtherFunctionType>
153 struct IsFunction : std::false_type {};
154
155 template <
156     typename FunctionType,
157     FunctionMoveCtor NTM,
158     size_t EmbedFunctorSize,
159     typename OtherFunctionType>
160 struct IsFunction<
161     ::folly::Function<FunctionType, NTM, EmbedFunctorSize>,
162     OtherFunctionType>
163     : std::is_same<
164           typename FunctionTypeTraits<FunctionType>::NonConstFunctionType,
165           typename FunctionTypeTraits<
166               OtherFunctionType>::NonConstFunctionType> {};
167
168 // Helper template to check if a functor can be called with arguments of type
169 // Args..., if it returns a type convertible to R (or R is void), and also is
170 // not a folly::Function.
171 // Function objects can constructed or assigned from types for which
172 // IsCallableHelper is true_type.
173 template <typename FunctionType>
174 struct IsCallableHelper {
175   using Traits = FunctionTypeTraits<FunctionType>;
176
177   template <typename F>
178   static std::integral_constant<bool, Traits::template IsCallable<F>::value>
179   test(int);
180   template <typename F>
181   static std::false_type test(...);
182 };
183
184 template <typename F, typename FunctionType>
185 struct IsCallable
186     : public std::integral_constant<
187           bool,
188           (!IsFunction<typename std::decay<F>::type, FunctionType>::value &&
189            decltype(IsCallableHelper<FunctionType>::template test<
190                     typename std::decay<F>::type>(0))::value)> {};
191
192 // MaybeUnaryOrBinaryFunction: helper template class for deriving
193 // Function from std::unary_function or std::binary_function
194 template <typename R, typename ArgsTuple>
195 struct MaybeUnaryOrBinaryFunctionImpl {
196   using result_type = R;
197 };
198
199 template <typename R, typename Arg>
200 struct MaybeUnaryOrBinaryFunctionImpl<R, std::tuple<Arg>>
201     : public std::unary_function<Arg, R> {};
202
203 template <typename R, typename Arg1, typename Arg2>
204 struct MaybeUnaryOrBinaryFunctionImpl<R, std::tuple<Arg1, Arg2>>
205     : public std::binary_function<Arg1, Arg2, R> {};
206
207 template <typename FunctionType>
208 using MaybeUnaryOrBinaryFunction = MaybeUnaryOrBinaryFunctionImpl<
209     typename FunctionTypeTraits<FunctionType>::ResultType,
210     typename FunctionTypeTraits<FunctionType>::ArgsTuple>;
211
212 // Invoke helper
213 template <typename F, typename... Args>
214 inline auto invoke(F&& f, Args&&... args)
215     -> decltype(std::forward<F>(f)(std::forward<Args>(args)...)) {
216   return std::forward<F>(f)(std::forward<Args>(args)...);
217 }
218
219 template <typename M, typename C, typename... Args>
220 inline auto invoke(M(C::*d), Args&&... args)
221     -> decltype(std::mem_fn(d)(std::forward<Args>(args)...)) {
222   return std::mem_fn(d)(std::forward<Args>(args)...);
223 }
224
225 // Executors helper class
226 template <typename FunctionType>
227 struct Executors {
228   class ExecutorIf;
229   class EmptyExecutor;
230   template <class F, class SelectFunctionTag>
231   class FunctorPtrExecutor;
232   template <class F, class SelectFunctionTag>
233   class FunctorExecutor;
234
235   using Traits = FunctionTypeTraits<FunctionType>;
236   using NonConstFunctionExecutors =
237       Executors<typename Traits::NonConstFunctionType>;
238   using ConstFunctionExecutors = Executors<typename Traits::ConstFunctionType>;
239   using InvokeFunctionPtr = typename Traits::template InvokeFunctionPtr<
240       Executors<FunctionType>::ExecutorIf>;
241 };
242
243 template <typename R, typename... Args>
244 class FunctionTypeTraits<R(Args...)>::ExecutorMixin {
245  public:
246   using ExecutorIf = typename Executors<R(Args...)>::ExecutorIf;
247   using InvokeFunctionPtr = typename Executors<R(Args...)>::InvokeFunctionPtr;
248
249   ExecutorMixin(InvokeFunctionPtr invoke_ptr) : invokePtr(invoke_ptr) {}
250   virtual ~ExecutorMixin() {}
251
252   template <typename F>
253   static F* selectFunctionHelper(F* f, SelectNonConstFunctionTag) {
254     return f;
255   }
256
257   template <typename F>
258   static F const* selectFunctionHelper(F* f, SelectConstFunctionTag) {
259     return f;
260   }
261
262   static R invokeEmpty(ExecutorIf*, Args&&...) {
263     throw std::bad_function_call();
264   }
265
266   template <typename Ex>
267   static R invokeFunctor(ExecutorIf* executor, Args&&... args) {
268     return static_cast<R>(folly::detail::function::invoke(
269         *Ex::getFunctor(executor), std::forward<Args>(args)...));
270   }
271
272   // invokePtr is of type
273   //   ReturnType (*)(ExecutorIf*, Args&&...)
274   // and it will be set to the address of one of the static functions above
275   // (invokeEmpty or invokeFunctor), which will invoke the stored callable
276   InvokeFunctionPtr const invokePtr;
277 };
278
279 template <typename R, typename... Args>
280 class FunctionTypeTraits<R(Args...) const>::ExecutorMixin {
281  public:
282   using ExecutorIf = typename Executors<R(Args...) const>::ExecutorIf;
283   using InvokeFunctionPtr =
284       typename Executors<R(Args...) const>::InvokeFunctionPtr;
285
286   ExecutorMixin(InvokeFunctionPtr invoke_ptr) : invokePtr(invoke_ptr) {}
287   virtual ~ExecutorMixin() {}
288
289   template <typename F>
290   static F* selectFunctionHelper(F const* f, SelectNonConstFunctionTag) {
291     return const_cast<F*>(f);
292   }
293
294   template <typename F>
295   static F const* selectFunctionHelper(F const* f, SelectConstFunctionTag) {
296     return f;
297   }
298
299   static R invokeEmpty(ExecutorIf const*, Args&&...) {
300     throw std::bad_function_call();
301   }
302
303   template <typename Ex>
304   static R invokeFunctor(ExecutorIf const* executor, Args&&... args) {
305     return static_cast<R>(folly::detail::function::invoke(
306         *Ex::getFunctor(executor), std::forward<Args>(args)...));
307   }
308
309   // invokePtr is of type
310   //   ReturnType (*)(ExecutorIf*, Args&&...)
311   // and it will be set to the address of one of the static functions above
312   // (invokeEmpty or invokeFunctor), which will invoke the stored callable
313   InvokeFunctionPtr const invokePtr;
314 };
315
316 template <class Function>
317 struct InvokeFromSharedPtr final {
318   std::shared_ptr<Function> ptr_;
319
320   explicit InvokeFromSharedPtr(std::shared_ptr<Function> ptr)
321       : ptr_(std::move(ptr)) {}
322
323   template <typename... Args>
324   auto operator()(Args&&... args)
325       -> decltype((*ptr_)(std::forward<Args>(args)...)) {
326     return (*ptr_)(std::forward<Args>(args)...);
327   }
328 };
329
330 } // namespace function
331 } // namespace detail
332 } // namespace folly