C++代碼
/** When this Future has completed, execute func which is a function that
takes one of:
(const) Try<T>&&
(const) Try<T>&
(const) Try<T>
(const) T&&
(const) T&
(const) T
(void)
Func shall return either another Future or a value.
A Future for the return type of func is returned.
Future<string> f2 = f1.then([](Try<T>&&) { return string("foo"); });
The Future given to the functor is ready, and the functor may call
value(), which may rethrow if this has captured an exception. If func
throws, the exception will be captured in the Future that is returned.
*/
template <
typename F,
typename FF = typename detail::FunctionReferenceToPointer<F>::type,
typename R = detail::callableResult<T, FF>>
typename R::Return then(F&& func) {
typedef typename R::Arg Arguments;
return thenImplementation<FF, R>(std::forward<FF>(func), Arguments());
}
大林上位機(jī)機(jī)器視覺,_常州電工培訓(xùn)_常州PLC培訓(xùn)_常州機(jī)器視覺培訓(xùn)_常州上位機(jī)培訓(xùn)_常州工業(yè)機(jī)器人培訓(xùn),最適合電工及plc編程人員學(xué)習(xí)的上位機(jī)機(jī)器視覺課程 大林老師:15861139266(微信同號)
template<typename F, typename... Args>
struct callableWith {
template<typename T,
typename = detail::resultOf<T, Args...>>
static constexpr std::true_type
check(std::nullptr_t) { return std::true_type{}; };
template<typename>
static constexpr std::false_type
check(...) { return std::false_type{}; };
typedef decltype(check<F>(nullptr)) type;
static constexpr bool value = type::value;
};
template<typename T, typename F>
struct callableResult {
typedef typename std::conditional<
callableWith<F>::value,
detail::argResult<false, F>,
typename std::conditional<
callableWith<F, T&&>::value,
detail::argResult<false, F, T&&>,
typename std::conditional<
callableWith<F, T&>::value,
detail::argResult<false, F, T&>,
typename std::conditional<
callableWith<F, Try<T>&&>::value,
detail::argResult<true, F, Try<T>&&>,
detail::argResult<true, F, Try<T>&>>::type>::type>::type>::type Arg;
typedef isFuture<typename Arg::Result> ReturnsFuture;
typedef Future<typename ReturnsFuture::Inner> Return;
};
template<typename F, typename... Args>
using resultOf = decltype(std::declval<F>()(std::declval<Args>()...));
這里一大波template我們一個一個來。FunctionReferenceToPointer可以無視掉,你可以想象成FF就是Fstd::declval 讓你把 F變成 F&&,所以可以用template<typename F, typename... Args>
using resultOf = decltype(std::declval<F>()(std::declval<Args>()...));
這樣的語法拿到F(Args args...) 的返回值,不管F是object還是lambda。這樣,resultOf可以拿到我們的callback的返回type。現(xiàn)在我們得把這個返回值跟下一個函數(shù)的argument對應(yīng)起來。這里我們用callableWithtemplate<typename F, typename... Args>
struct callableWith {
template<typename T,
typename = detail::resultOf<T, Args...>>
static constexpr std::true_type
check(std::nullptr_t) { return std::true_type{}; };
template<typename>
static constexpr std::false_type
check(...) { return std::false_type{}; };
typedef decltype(check<F>(nullptr)) type;
static constexpr bool value = type::value;
};
這里check有兩個specialization,一個在編譯時候會返回true一個會返回false。注意只要不符合第一個specialization的都是false,也就是說resultOf沒有成功,check(nullptr) 就是false type。這個技巧叫做Substitution Failure Is Not An Error SFINAE - cppreference.com 。再配倒數(shù)第二行的typedef,如果 F可以接受args,那么callableWith<F>(Args args...)::value == true type。最后,把所有我們允許的類用std::conditional一個一個試過去template<typename T, typename F>
struct callableResult {
typedef typename std::conditional<
callableWith<F>::value,
detail::argResult<false, F>,
typename std::conditional<
callableWith<F, T&&>::value,
detail::argResult<false, F, T&&>,
typename std::conditional<
callableWith<F, T&>::value,
detail::argResult<false, F, T&>,
typename std::conditional<
callableWith<F, Try<T>&&>::value,
detail::argResult<true, F, Try<T>&&>,
detail::argResult<true, F, Try<T>&>>::type>::type>::type>::type Arg;
typedef isFuture<typename Arg::Result> ReturnsFuture;
typedef Future<typename ReturnsFuture::Inner> Return;
};