namespace detail {
template <class> struct Core;
template <class...> struct VariadicContext;
+
+ template <class T>
+ struct AliasIfVoid {
+ typedef typename std::conditional<
+ std::is_same<T, void>::value,
+ int,
+ T>::type type;
+ };
}
+
template <class> struct Promise;
template <typename T> struct isFuture;
Future<typename std::result_of<F(Try<T>&&)>::type> >::type
then(F&& func);
+ /// Variant where func takes a T directly, bypassing a try. Any exceptions
+ /// will be implicitly passed on to the resultant Future.
+ ///
+ /// Future<int> f = makeFuture<int>(42).then([](int i) { return i+1; });
+ template <class F>
+ typename std::enable_if<
+ !std::is_same<T, void>::value &&
+ !isFuture<typename std::result_of<
+ F(typename detail::AliasIfVoid<T>::type&&)>::type>::value,
+ Future<typename std::result_of<
+ F(typename detail::AliasIfVoid<T>::type&&)>::type> >::type
+ then(F&& func);
+
+ /// Like the above variant, but for void futures. That is, func takes no
+ /// argument.
+ ///
+ /// Future<int> f = makeFuture().then([] { return 42; });
+ template <class F>
+ typename std::enable_if<
+ std::is_same<T, void>::value &&
+ !isFuture<typename std::result_of<F()>::type>::value,
+ Future<typename std::result_of<F()>::type> >::type
+ then(F&& func);
+
/// Variant where func returns a Future<T> instead of a T. e.g.
///
/// Future<string> f2 = f1.then(
Future<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
then(F&& func);
+ /// Variant where func returns a Future<T2> and takes a T directly, bypassing
+ /// a Try. Any exceptions will be implicitly passed on to the resultant
+ /// Future. For example,
+ ///
+ /// Future<int> f = makeFuture<int>(42).then(
+ /// [](int i) { return makeFuture<int>(i+1); });
+ template <class F>
+ typename std::enable_if<
+ !std::is_same<T, void>::value &&
+ isFuture<typename std::result_of<
+ F(typename detail::AliasIfVoid<T>::type&&)>::type>::value,
+ Future<typename std::result_of<
+ F(typename detail::AliasIfVoid<T>::type&&)>::type::value_type> >::type
+ then(F&& func);
+
+ /// Like the above variant, but for void futures. That is, func takes no
+ /// argument and returns a future.
+ ///
+ /// Future<int> f = makeFuture().then(
+ /// [] { return makeFuture<int>(42); });
+ template <class F>
+ typename std::enable_if<
+ std::is_same<T, void>::value &&
+ isFuture<typename std::result_of<F()>::type>::value,
+ Future<typename std::result_of<F()>::type::value_type> >::type
+ then(F&& func);
+
/// Variant where func is an ordinary function (static method, method)
///
/// R doWork(Try<T>&&);
});
}
+ // Same as above, but func takes void instead of Try<void>&&
+ template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
+ typename std::enable_if<
+ std::is_same<T, void>::value && !isFuture<R>::value, Future<R>>::type
+ inline then(Caller *instance, R(Caller::*func)()) {
+ return then([instance, func]() {
+ return (instance->*func)();
+ });
+ }
+
+ // Same as above, but func takes T&& instead of Try<T>&&
+ template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
+ typename std::enable_if<
+ !std::is_same<T, void>::value && !isFuture<R>::value, Future<R>>::type
+ inline then(
+ Caller *instance,
+ R(Caller::*func)(typename detail::AliasIfVoid<T>::type&&)) {
+ return then([instance, func](T&& t) {
+ return (instance->*func)(std::move(t));
+ });
+ }
+
/// Variant where func returns a Future<R> instead of a R. e.g.
///
/// struct Worker {
});
}
+ // Same as above, but func takes void instead of Try<void>&&
+ template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
+ typename std::enable_if<
+ std::is_same<T, void>::value && isFuture<R>::value, R>::type
+ inline then(Caller *instance, R(Caller::*func)()) {
+ return then([instance, func]() {
+ return (instance->*func)();
+ });
+ }
+
+ // Same as above, but func takes T&& instead of Try<T>&&
+ template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
+ typename std::enable_if<
+ !std::is_same<T, void>::value && isFuture<R>::value, R>::type
+ inline then(
+ Caller *instance,
+ R(Caller::*func)(typename detail::AliasIfVoid<T>::type&&)) {
+ return then([instance, func](T&& t) {
+ return (instance->*func)(std::move(t));
+ });
+ }
+
/// Convenience method for ignoring the value and creating a Future<void>.
/// Exceptions still propagate.
Future<void> then();