proxygen
Invoke.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present 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 #include <functional>
20 #include <type_traits>
21 
22 #include <folly/Preprocessor.h>
23 #include <folly/Traits.h>
24 
36 #if __cpp_lib_invoke >= 201411 || _MSC_VER
37 
38 namespace folly {
39 
40 /* using override */ using std::invoke;
41 }
42 
43 #else
44 
45 namespace folly {
46 
47 // mimic: std::invoke, C++17
48 template <typename F, typename... Args>
49 constexpr auto invoke(F&& f, Args&&... args) noexcept(
50  noexcept(static_cast<F&&>(f)(static_cast<Args&&>(args)...)))
51  -> decltype(static_cast<F&&>(f)(static_cast<Args&&>(args)...)) {
52  return static_cast<F&&>(f)(static_cast<Args&&>(args)...);
53 }
54 template <typename M, typename C, typename... Args>
55 constexpr auto invoke(M(C::*d), Args&&... args)
56  -> decltype(std::mem_fn(d)(static_cast<Args&&>(args)...)) {
57  return std::mem_fn(d)(static_cast<Args&&>(args)...);
58 }
59 
60 } // namespace folly
61 
62 #endif
63 
64 // Only available in >= MSVC 2017 15.3 in C++17
65 #if __cpp_lib_is_invocable >= 201703 || \
66  (_MSC_VER >= 1911 && _MSVC_LANG > 201402)
67 
68 namespace folly {
69 
70 /* using override */ using std::invoke_result;
71 /* using override */ using std::invoke_result_t;
72 /* using override */ using std::is_invocable;
73 /* using override */ using std::is_invocable_r;
74 /* using override */ using std::is_nothrow_invocable;
75 /* using override */ using std::is_nothrow_invocable_r;
76 
77 } // namespace folly
78 
79 #else
80 
81 namespace folly {
82 
83 namespace invoke_detail {
84 
85 template <typename F, typename... Args>
86 using invoke_result_ =
87  decltype(invoke(std::declval<F>(), std::declval<Args>()...));
88 
89 template <typename F, typename... Args>
91  : bool_constant<noexcept(
92  invoke(std::declval<F>(), std::declval<Args>()...))> {};
93 
94 // from: http://en.cppreference.com/w/cpp/types/result_of, CC-BY-SA
95 
96 template <typename Void, typename F, typename... Args>
97 struct invoke_result {};
98 
99 template <typename F, typename... Args>
100 struct invoke_result<void_t<invoke_result_<F, Args...>>, F, Args...> {
101  using type = invoke_result_<F, Args...>;
102 };
103 
104 template <typename Void, typename F, typename... Args>
106 
107 template <typename F, typename... Args>
108 struct is_invocable<void_t<invoke_result_<F, Args...>>, F, Args...>
109  : std::true_type {};
110 
111 template <typename Void, typename R, typename F, typename... Args>
113 
114 template <typename R, typename F, typename... Args>
115 struct is_invocable_r<void_t<invoke_result_<F, Args...>>, R, F, Args...>
116  : std::is_convertible<invoke_result_<F, Args...>, R> {};
117 
118 template <typename Void, typename F, typename... Args>
120 
121 template <typename F, typename... Args>
122 struct is_nothrow_invocable<void_t<invoke_result_<F, Args...>>, F, Args...>
123  : invoke_nothrow_<F, Args...> {};
124 
125 template <typename Void, typename R, typename F, typename... Args>
127 
128 template <typename R, typename F, typename... Args>
129 struct is_nothrow_invocable_r<void_t<invoke_result_<F, Args...>>, R, F, Args...>
131  std::is_convertible<invoke_result_<F, Args...>, R>,
132  invoke_nothrow_<F, Args...>> {};
133 
134 } // namespace invoke_detail
135 
136 // mimic: std::invoke_result, C++17
137 template <typename F, typename... Args>
138 struct invoke_result : invoke_detail::invoke_result<void, F, Args...> {};
139 
140 // mimic: std::invoke_result_t, C++17
141 template <typename F, typename... Args>
142 using invoke_result_t = typename invoke_result<F, Args...>::type;
143 
144 // mimic: std::is_invocable, C++17
145 template <typename F, typename... Args>
146 struct is_invocable : invoke_detail::is_invocable<void, F, Args...> {};
147 
148 // mimic: std::is_invocable_r, C++17
149 template <typename R, typename F, typename... Args>
150 struct is_invocable_r : invoke_detail::is_invocable_r<void, R, F, Args...> {};
151 
152 // mimic: std::is_nothrow_invocable, C++17
153 template <typename F, typename... Args>
155  : invoke_detail::is_nothrow_invocable<void, F, Args...> {};
156 
157 // mimic: std::is_nothrow_invocable_r, C++17
158 template <typename R, typename F, typename... Args>
160  : invoke_detail::is_nothrow_invocable_r<void, R, F, Args...> {};
161 
162 } // namespace folly
163 
164 #endif
165 
166 namespace folly {
167 namespace detail {
168 
169 struct invoke_private_overload;
170 
171 template <typename Invoke>
173  public:
174  template <typename... Args>
175  struct invoke_result : folly::invoke_result<Invoke, Args...> {};
176  template <typename... Args>
178  template <typename... Args>
179  struct is_invocable : folly::is_invocable<Invoke, Args...> {};
180  template <typename R, typename... Args>
181  struct is_invocable_r : folly::is_invocable_r<R, Invoke, Args...> {};
182  template <typename... Args>
183  struct is_nothrow_invocable : folly::is_nothrow_invocable<Invoke, Args...> {};
184  template <typename R, typename... Args>
186  : folly::is_nothrow_invocable_r<R, Invoke, Args...> {};
187 
188  template <typename... Args>
189  static constexpr auto invoke(Args&&... args) noexcept(
190  noexcept(Invoke{}(static_cast<Args&&>(args)...)))
191  -> decltype(Invoke{}(static_cast<Args&&>(args)...)) {
192  return Invoke{}(static_cast<Args&&>(args)...);
193  }
194 
196 };
197 
198 } // namespace detail
199 } // namespace folly
200 
201 /***
202  * FOLLY_CREATE_FREE_INVOKE_TRAITS
203  *
204  * Used to create traits container, bound to a specific free-invocable name,
205  * with the following member traits types and aliases:
206  *
207  * * invoke_result
208  * * invoke_result_t
209  * * is_invocable
210  * * is_invocable_r
211  * * is_nothrow_invocable
212  * * is_nothrow_invocable_r
213  *
214  * The container also has a static member function:
215  *
216  * * invoke
217  *
218  * And a member type alias:
219  *
220  * * invoke_type
221  *
222  * These members have behavior matching the behavior of C++17's corresponding
223  * invocation traits types, aliases, and functions, but substituting canonical
224  * invocation with member invocation.
225  *
226  * Example:
227  *
228  * FOLLY_CREATE_FREE_INVOKE_TRAITS(foo_invoke_traits, foo);
229  *
230  * The traits container type `foo_invoke_traits` is generated in the current
231  * namespace and has the listed member types and aliases. They may be used as
232  * follows:
233  *
234  * namespace Deep {
235  * struct CanFoo {};
236  * int foo(CanFoo const&, Bar&) { return 1; }
237  * int foo(CanFoo&&, Car&&) noexcept { return 2; }
238  * }
239  *
240  * using traits = foo_invoke_traits;
241  *
242  * traits::invoke(Deep::CanFoo{}, Car{}) // 2
243  *
244  * traits::invoke_result<Deep::CanFoo, Bar&> // has member
245  * traits::invoke_result_t<Deep::CanFoo, Bar&> // int
246  * traits::invoke_result<Deep::CanFoo, Bar&&> // empty
247  * traits::invoke_result_t<Deep::CanFoo, Bar&&> // error
248  *
249  * traits::is_invocable<CanFoo, Bar&>::value // true
250  * traits::is_invocable<CanFoo, Bar&&>::value // false
251  *
252  * traits::is_invocable_r<int, CanFoo, Bar&>::value // true
253  * traits::is_invocable_r<char*, CanFoo, Bar&>::value // false
254  *
255  * traits::is_nothrow_invocable<CanFoo, Bar&>::value // false
256  * traits::is_nothrow_invocable<CanFoo, Car&&>::value // true
257  *
258  * traits::is_nothrow_invocable<int, CanFoo, Bar&>::value // false
259  * traits::is_nothrow_invocable<char*, CanFoo, Bar&>::value // false
260  * traits::is_nothrow_invocable<int, CanFoo, Car&&>::value // true
261  * traits::is_nothrow_invocable<char*, CanFoo, Car&&>::value // false
262  *
263  * When a name has a primary definition in a fixed namespace and alternate
264  * definitions in the namespaces of its arguments, the primary definition may
265  * automatically be found as follows:
266  *
267  * FOLLY_CREATE_FREE_INVOKE_TRAITS(swap_invoke_traits, swap, std);
268  *
269  * In this case, `swap_invoke_traits::invoke(int&, int&)` will use the primary
270  * definition found in `namespace std` relative to the current namespace, which
271  * may be equivalent to `namespace ::std`. In contrast:
272  *
273  * namespace Deep {
274  * struct HasData {};
275  * void swap(HasData&, HasData&) { throw 7; }
276  * }
277  *
278  * using traits = swap_invoke_traits;
279  *
280  * HasData a, b;
281  * traits::invoke(a, b); // throw 7
282  */
283 #define FOLLY_CREATE_FREE_INVOKE_TRAITS(classname, funcname, ...) \
284  namespace classname##__folly_detail_invoke_ns { \
285  namespace classname##__folly_detail_invoke_ns_inline { \
286  FOLLY_PUSH_WARNING \
287  FOLLY_CLANG_DISABLE_WARNING("-Wunused-function") \
288  void funcname(::folly::detail::invoke_private_overload&); \
289  FOLLY_POP_WARNING \
290  } \
291  using FB_ARG_2_OR_1( \
292  classname##__folly_detail_invoke_ns_inline \
293  FOLLY_PP_DETAIL_APPEND_VA_ARG(__VA_ARGS__))::funcname; \
294  struct classname##__folly_detail_invoke { \
295  template <typename... Args> \
296  constexpr auto operator()(Args&&... args) const \
297  noexcept(noexcept(funcname(static_cast<Args&&>(args)...))) \
298  -> decltype(funcname(static_cast<Args&&>(args)...)) { \
299  return funcname(static_cast<Args&&>(args)...); \
300  } \
301  }; \
302  } \
303  struct classname : ::folly::detail::free_invoke_proxy< \
304  classname##__folly_detail_invoke_ns:: \
305  classname##__folly_detail_invoke> {}
306 
307 namespace folly {
308 namespace detail {
309 
310 template <typename Invoke>
312  public:
313  template <typename O, typename... Args>
314  struct invoke_result : folly::invoke_result<Invoke, O, Args...> {};
315  template <typename O, typename... Args>
317  template <typename O, typename... Args>
318  struct is_invocable : folly::is_invocable<Invoke, O, Args...> {};
319  template <typename R, typename O, typename... Args>
320  struct is_invocable_r : folly::is_invocable_r<R, Invoke, O, Args...> {};
321  template <typename O, typename... Args>
323  : folly::is_nothrow_invocable<Invoke, O, Args...> {};
324  template <typename R, typename O, typename... Args>
326  : folly::is_nothrow_invocable_r<R, Invoke, O, Args...> {};
327 
328  template <typename O, typename... Args>
329  static constexpr auto invoke(O&& o, Args&&... args) noexcept(
330  noexcept(Invoke{}(static_cast<O&&>(o), static_cast<Args&&>(args)...)))
331  -> decltype(Invoke{}(static_cast<O&&>(o), static_cast<Args&&>(args)...)) {
332  return Invoke{}(static_cast<O&&>(o), static_cast<Args&&>(args)...);
333  }
334 
336 };
337 
338 } // namespace detail
339 } // namespace folly
340 
341 /***
342  * FOLLY_CREATE_MEMBER_INVOKE_TRAITS
343  *
344  * Used to create traits container, bound to a specific member-invocable name,
345  * with the following member traits types and aliases:
346  *
347  * * invoke_result
348  * * invoke_result_t
349  * * is_invocable
350  * * is_invocable_r
351  * * is_nothrow_invocable
352  * * is_nothrow_invocable_r
353  *
354  * The container also has a static member function:
355  *
356  * * invoke
357  *
358  * And a member type alias:
359  *
360  * * invoke_type
361  *
362  * These members have behavior matching the behavior of C++17's corresponding
363  * invocation traits types, aliases, and functions, but substituting canonical
364  * invocation with member invocation.
365  *
366  * Example:
367  *
368  * FOLLY_CREATE_MEMBER_INVOKE_TRAITS(foo_invoke_traits, foo);
369  *
370  * The traits container type `foo_invoke_traits` is generated in the current
371  * namespace and has the listed member types and aliases. They may be used as
372  * follows:
373  *
374  * struct CanFoo {
375  * int foo(Bar&) { return 1; }
376  * int foo(Car&&) noexcept { return 2; }
377  * };
378  *
379  * using traits = foo_invoke_traits;
380  *
381  * traits::invoke(CanFoo{}, Car{}) // 2
382  *
383  * traits::invoke_result<CanFoo, Bar&> // has member
384  * traits::invoke_result_t<CanFoo, Bar&> // int
385  * traits::invoke_result<CanFoo, Bar&&> // empty
386  * traits::invoke_result_t<CanFoo, Bar&&> // error
387  *
388  * traits::is_invocable<CanFoo, Bar&>::value // true
389  * traits::is_invocable<CanFoo, Bar&&>::value // false
390  *
391  * traits::is_invocable_r<int, CanFoo, Bar&>::value // true
392  * traits::is_invocable_r<char*, CanFoo, Bar&>::value // false
393  *
394  * traits::is_nothrow_invocable<CanFoo, Bar&>::value // false
395  * traits::is_nothrow_invocable<CanFoo, Car&&>::value // true
396  *
397  * traits::is_nothrow_invocable<int, CanFoo, Bar&>::value // false
398  * traits::is_nothrow_invocable<char*, CanFoo, Bar&>::value // false
399  * traits::is_nothrow_invocable<int, CanFoo, Car&&>::value // true
400  * traits::is_nothrow_invocable<char*, CanFoo, Car&&>::value // false
401  */
402 #define FOLLY_CREATE_MEMBER_INVOKE_TRAITS(classname, membername) \
403  struct classname##__folly_detail_member_invoke { \
404  template <typename O, typename... Args> \
405  constexpr auto operator()(O&& o, Args&&... args) const noexcept(noexcept( \
406  static_cast<O&&>(o).membername(static_cast<Args&&>(args)...))) \
407  -> decltype( \
408  static_cast<O&&>(o).membername(static_cast<Args&&>(args)...)) { \
409  return static_cast<O&&>(o).membername(static_cast<Args&&>(args)...); \
410  } \
411  }; \
412  struct classname : ::folly::detail::member_invoke_proxy< \
413  classname##__folly_detail_member_invoke> {}
auto f
typename invoke_result< F, Args... >::type invoke_result_t
Definition: Invoke.h:142
PskType type
constexpr auto invoke(M(C::*d), Args &&...args) -> decltype(std::mem_fn(d)(static_cast< Args && >(args)...))
Definition: Invoke.h:55
folly::invoke_result_t< Invoke, O, Args... > invoke_result_t
Definition: Invoke.h:316
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
bool_constant< true > true_type
Definition: gtest-port.h:2210
constexpr auto invoke(F &&f, Args &&...args) noexcept(noexcept(static_cast< F && >(f)(static_cast< Args && >(args)...))) -> decltype(static_cast< F && >(f)(static_cast< Args && >(args)...))
Definition: Invoke.h:49
std::integral_constant< bool, B > bool_constant
Definition: Traits.h:145
PolymorphicAction< internal::InvokeAction< FunctionImpl > > Invoke(FunctionImpl function_impl)
decltype(invoke(std::declval< F >(), std::declval< Args >()...)) invoke_result_
Definition: Invoke.h:87
type_t< void, Ts... > void_t
Definition: Traits.h:302
static constexpr auto invoke(O &&o, Args &&...args) noexcept(noexcept(Invoke{}(static_cast< O && >(o), static_cast< Args && >(args)...))) -> decltype(Invoke
Definition: Invoke.h:329
#define C(name, bit)
Definition: CpuId.h:204
**Optimized Holders **The template hazptr_array< M > provides most of the functionality *of M hazptr_holder s but with faster construction destruction *for M
Definition: Hazptr.h:104
bool_constant< false > false_type
Definition: gtest-port.h:2209
static constexpr auto invoke(Args &&...args) noexcept(noexcept(Invoke{}(static_cast< Args && >(args)...))) -> decltype(Invoke
Definition: Invoke.h:189
folly::invoke_result_t< Invoke, Args... > invoke_result_t
Definition: Invoke.h:177