【问题标题】:Create a tuple from the results of a callable tuple从可调用元组的结果创建一个元组
【发布时间】:2016-03-07 06:00:04
【问题描述】:

我有一个可调用类型的元组。

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

我想创建另一个具有每个可调用结果类型的元组。例如,funcs 包含 int-&gt;intdouble-&gt;std::string

如何创建一个依赖于funcs 中每个元素的results 元组,它可能看起来像这样。

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

【问题讨论】:

    标签: c++ tuples stdtuple


    【解决方案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; };
    
    }
    

    【讨论】:

    • 如果我确切地知道funcs 是什么,这将有效。但是有可能有某种auto x = [](auto funcs){ /*use your code here*/ }
    • 这适用于任意元组类型。 C++ 中每个变量的类型都是已知的,因此 decltype(some_tuple_variable) 将始终为您提供元组的类型。
    • 这不起作用auto x = [](auto funcs){ TupleHandler&lt;decltype(funcs)&gt;::ReturnTypeTuple results; }
    • 刚刚将其添加到答案中的代码中。它需要一个“类型名”,但可以正常工作。 “类型名”是必需的,因为它不知道基于什么不同的东西 funcs 可能是整个语句的样子。所以它需要提示结尾的“东西”是一种类型。
    • 缺少“typename”的编译器错误非常有用:在 'TupleHandler::ReturnTypeTuple' 之前需要 'typename' 因为 'TupleHandler' 是依赖范围
    【解决方案2】:

    一种非递归方式:

    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

    【讨论】:

      【解决方案3】:

      std::function 有一个名为 result_type 的成员 typedef。随便用吧。

      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
      

      【讨论】:

      • 这个版本更好?。
      • 我不知道你可以“调用”一个没有主体的函数。这……太迷人了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多