2 * Copyright 2016 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 // included by Future.h, do not include directly.
23 template <class> class Promise;
26 struct isFuture : std::false_type {
27 using Inner = typename Unit::Lift<T>::type;
31 struct isFuture<Future<T>> : std::true_type {
36 struct isTry : std::false_type {};
39 struct isTry<Try<T>> : std::true_type {};
43 template <class> class Core;
44 template <class...> struct CollectAllVariadicContext;
45 template <class...> struct CollectVariadicContext;
46 template <class> struct CollectContext;
48 template<typename F, typename... Args>
49 using resultOf = decltype(std::declval<F>()(std::declval<Args>()...));
51 template <typename...>
54 template <typename Arg, typename... Args>
55 struct ArgType<Arg, Args...> {
61 typedef void FirstArg;
64 template <bool isTry, typename F, typename... Args>
66 using Result = resultOf<F, Args...>;
69 template<typename F, typename... Args>
72 typename = detail::resultOf<T, Args...>>
73 static constexpr std::true_type
74 check(std::nullptr_t) { return std::true_type{}; };
77 static constexpr std::false_type
78 check(...) { return std::false_type{}; };
80 typedef decltype(check<F>(nullptr)) type;
81 static constexpr bool value = type::value;
84 template<typename T, typename F>
85 struct callableResult {
86 typedef typename std::conditional<
87 callableWith<F>::value,
88 detail::argResult<false, F>,
89 typename std::conditional<
90 callableWith<F, T&&>::value,
91 detail::argResult<false, F, T&&>,
92 typename std::conditional<
93 callableWith<F, T&>::value,
94 detail::argResult<false, F, T&>,
95 typename std::conditional<
96 callableWith<F, Try<T>&&>::value,
97 detail::argResult<true, F, Try<T>&&>,
98 detail::argResult<true, F, Try<T>&>>::type>::type>::type>::type Arg;
99 typedef isFuture<typename Arg::Result> ReturnsFuture;
100 typedef Future<typename ReturnsFuture::Inner> Return;
103 template <typename L>
104 struct Extract : Extract<decltype(&L::operator())> { };
106 template <typename Class, typename R, typename... Args>
107 struct Extract<R(Class::*)(Args...) const> {
108 typedef isFuture<R> ReturnsFuture;
109 typedef Future<typename ReturnsFuture::Inner> Return;
110 typedef typename ReturnsFuture::Inner RawReturn;
111 typedef typename ArgType<Args...>::FirstArg FirstArg;
114 template <typename Class, typename R, typename... Args>
115 struct Extract<R(Class::*)(Args...)> {
116 typedef isFuture<R> ReturnsFuture;
117 typedef Future<typename ReturnsFuture::Inner> Return;
118 typedef typename ReturnsFuture::Inner RawReturn;
119 typedef typename ArgType<Args...>::FirstArg FirstArg;
122 // gcc-4.8 refuses to capture a function reference in a lambda. This can be
123 // mitigated by casting them to function pointer types first. The following
124 // helper is used in Future.h to achieve that where necessary.
125 // When compiling with gcc versions 4.9 and up, as well as clang, we do not
126 // need to apply FunctionReferenceToPointer (i.e. T can be used instead of
127 // FunctionReferenceToPointer<T>).
128 // Applying FunctionReferenceToPointer first, the code works on all tested
129 // compiler versions: gcc 4.8 and above, cland 3.5 and above.
131 template <typename T>
132 struct FunctionReferenceToPointer {
136 template <typename R, typename... Args>
137 struct FunctionReferenceToPointer<R (&)(Args...)> {
138 using type = R (*)(Args...);