【问题标题】:Transform tuple type to another tuple type将元组类型转换为另一种元组类型
【发布时间】:2020-04-09 00:25:20
【问题描述】:

假设我有一个元组类型std::tuple<x,y,z>,或者可能是std::tuple<a,b>。我想要一种通用的方法来转换我的元组中的类型,例如“功能化”得到

std::tuple<std::function<void(x)>,
           std::function<void(y)>,
           std::function<void(z)>>

或者也许可以为 shared_pointers 获取存储空间,例如

std::tuple<std::shared_pointer<a>,
           std::shared_pointer<b>>

如何使用 C++17 实现这一点? C++20 的答案很有趣,但不适用于我目前的情况。

动机: 我有一个类将由任意且不一定唯一的类型列表参数化,并且希望列表中的每种类型都有一个 std::function 成员。

【问题讨论】:

    标签: c++ variadic-templates


    【解决方案1】:

    模板专业化可能是最简单的方法。

    template <typename T>
    struct functionize;
    
    template <typename... Ts>
    struct functionize<std::tuple<Ts...>> {
        using type = std::tuple<std::function<void(Ts)>...>;
    }
    
    using MyTuple = std::tuple<int, double, char>;
    using MyTupleFunctionized = typename functionize<MyTuple>::type;
    

    为了使其更通用,您可以接受模板模板参数以应用于包。

    template <typename Tuple, template <typename> typename Component>
    struct transform_tuple;
    
    template <typename... Ts, template <typename> typename Component>
    struct transform_tuple<std::tuple<Ts...>, Component> {
        using type = std::tuple<Component<Ts>...>;
    }
    
    using MyTuple = std::tuple<int, double, char>;
    using MyTransformedTuple = typename transform_tuple<MyTuple, std::shared_ptr>::type;
    

    更通用的解决方案最适合c++17 或更高版本。在此之前,它只会匹配具有恰好 1 个参数的模板。在c++17 之后,它还可以匹配std::vector 之类的东西,它有两个模板参数,而第二个模板参数有一个默认参数。

    编辑:
    正如 @Jarod42 和 @Caleth 在 cmets 中所指出的,我们可以在这方面进行更多改进。

    template <typename Tuple, template <typename...> typename Component>
    struct transform_tuple;
    

    模板模板参数的参数包允许我们从c++11 传入类似std::vector 的内容并转发。如果我们想要传递混合类型和非类型参数的东西,比如std::array,那只会留下问题。

    我们可以通过使用模板别名来部分解决这个问题。

    template <typename T>
    using FixedArray10 = std::array<T, 10>;
    
    using MyTransformedTuple = typename transform_tuple<MyTuple, FixedArray10>::type;
    

    【讨论】:

    • 你可以在 C++11 中做template &lt;typename Tuple, template &lt;typename...&gt; typename Component&gt; struct transform_tuple;
    • 在 c++17 之前,您可能仍会为 Component 创建别名:template &lt;typename T&gt; using Vec = std::vector&lt;T&gt;;transform_tuple&lt;MyTuple, Vec&gt;::type。(因此可以处理 std::array&lt;T, 42&gt;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 2011-01-24
    • 2020-12-02
    相关资源
    最近更新 更多