假设你有三个可调用的对象f g h,你想得到
h(g(f(args...)))
,您可以这样做:
template <size_t first, class ChainedFns, class... Args>
decltype(auto) Call(ChainedFns &&fns, Args&&... args) {
if constexpr (std::tuple_size_v<std::decay_t<ChainedFns>> == 0)
return;
else if constexpr (first < std::tuple_size_v<std::decay_t<ChainedFns>>-1)
return Call<first + 1>(fns, std::invoke(std::get<first>(std::forward<ChainedFns>(fns)), std::forward<Args>(args)...));
else if constexpr (first == std::tuple_size_v<std::decay_t<ChainedFns>>-1)
return std::invoke(std::get<first>(std::forward<ChainedFns>(fns)), std::forward<Args>(args)...);
}
template <size_t first, class ChainedFns, class... Args>
struct invoke_result_of_chained_callables {
using type = decltype(Call<first>(std::declval<ChainedFns>(), std::declval<Args>()...));
};
template <size_t first, class ChainedFns, class... Args>
using invoke_result_of_chained_callables_t = typename invoke_result_of_chained_callables<first, ChainedFns, Args...>::type;
int main() {
auto fns = std::make_tuple(
[](auto) { return 0; }, // f
[](auto x) { return std::vector{ x }; }, // g
[](auto x) { return x.size(); } // h
);
using type = decltype(Call<0>(fns, nullptr));
static_assert(std::is_same_v<type, size_t>);
using type1 = invoke_result_of_chained_callables_t<0, decltype(fns), std::nullptr_t>;
static_assert(std::is_same_v<type, type1>);
return 0;
}
此代码段也适用于任意数量的链接可调用对象。