2016-03-07 50 views
1

我有一個可調用類型的元組。從可調用元組的結果創建一個元組

std::tuple<std::function<int(int)>, std::function<std::string(double)>> funcs; 

我想創建一個具有每個調用的結果的另一種類型的元組。例如,funcs包含int->intdouble->std::string

如何創建一個元組results依賴於funcs每一個元素,它可能看起來是這樣的。

std::tuple<int, std::string> results; 

回答

1
#include <tuple> 
#include <functional> 
#include <string> 


// takes an arbitrary tuple of std::functions and creates a 
// tuple of the return types of those std::functions 
template<class T, class... Types> 
struct TupleHandler; 

// handles the recursive inheritance base case when all the 
// elements of the tuple have been processed 
template<class... Types> 
    struct TupleHandler<std::tuple<>, Types...> { 
    using ReturnTypeTuple = std::tuple<Types...>; 
    }; 

// Strips off the first std::function in the tuple, determines 
// its return type and passes the remaining parts on to have the next element 
// processed 
template<class Return, class... Rest, class... Tail, class... Types> 
struct TupleHandler<std::tuple<std::function<Return(Rest...)>, Tail...>, Types...> : TupleHandler<std::tuple<Tail...>, Types..., Return> { 
    using ReturnTypeTuple = typename TupleHandler<std::tuple<Tail...>, Types..., Return>::ReturnTypeTuple; 
}; 

int main() 
{ 
    std::tuple<std::function<int(int)>, std::function<std::string(double)>> funcs; 

    // Of course for this simple use case you could have just used std::make_tuple, but it still demonstrates the solution 
    TupleHandler<decltype(funcs)>::ReturnTypeTuple return_value_tuple(std::get<0>(funcs)(1), std::get<1>(funcs)(4.4)); 

    // added per comment 
    auto x = [](auto funcs){ typename TupleHandler<decltype(funcs)>::ReturnTypeTuple results; }; 

} 
+0

這個作品,如果我知道funcs'到底是什麼'。但它可能有某種'auto x = [](auto funcs){/ *在這裏使用你的代碼* /}' – nRewik

+0

這適用於任意的元組類型。 C++中每個變量的類型都是已知的,所以decltype(some_tuple_variable)總是會給出元組的類型。 – xaxxon

+0

這不起作用'auto x = [](auto funcs){TupleHandler :: ReturnTypeTuple結果; }' – nRewik

1

一種非遞歸的方式:

template <typename Func> struct result_of_function; 

template <typename Ret, typename ...Args> 
struct result_of_function<std::function<Ret(Args...)>> 
{ 
    using type = Ret; 
}; 

template <typename... Tuples> struct tuple_ret_function; 

template <typename... Funcs> 
struct tuple_ret_function<std::tuple<Funcs...>> 
{ 
    using type = std::tuple<typename result_of_function<Funcs>::type...>; 
}; 

Demo

1

std::function具有一個typedef稱爲result_type構件。只要使用它。

template<class... Funcs> 
auto tuple_function_ret_impl(std::tuple<Funcs...>) 
    -> std::tuple<typename Funcs::result_type ...>; 

template<class Tuple> 
using tuple_function_ret = decltype(tuple_function_ret_impl(Tuple())); 

Demo

using func_tuple = std::tuple<std::function<int(int)>, 
           std::function<std::string(double)>>; 

using ret_tuple = tuple_function_ret<func_tuple>; 
using ret_tuple = std::tuple<int, std::string>; // OK 
+0

這個版本更好。 – nRewik

+0

我不知道你可以在沒有身體的情況下「調用」一個函數。這真是令人着迷。 – xaxxon