【问题标题】:C++ 11 - Tuple of Arrays from Array of TupleC++ 11 - 来自元组数组的数组元组
【发布时间】:2013-06-23 18:17:38
【问题描述】:

给定一个 std::tuple,例如:

std::tuple<int, float, char>

我想生成这样的类型:

std::tuple<std::vector<int>, std::vector<float>, std::vector<char>>

如您所见,是原始类型向量的元组。 这是标准场景:

typedef std::tuple<int, float, char>    Struct;          // scenario 1
typedef std::vector<Struct>             ArrayOfStructs;  // scenario 2
typedef HereIsTheQuestion<Struct>::Type StructOfArrays;  // scenario 3

场景 1 的访问方式如下:

Struct x = ...; // single tuple
std::get<0>(x) = 11;
// etc.

场景 2 的访问方式如下:

ArrayOfStructs xs = ...; // array of tuples
for (size_t i=0; i<xs.size(); ++i) {
    std::get<0>(xs[i]) = 11;
    // etc.
}

场景 3 的访问方式如下:

StructsOfArrays xs = ...; // single tuple of arrays
size_t n = std::get<0>(xs).size(); // first tuple array size
for (size_t i=0; i<n; ++i) {
    std::get<0>(xs)[i] = 11;
    // etc.
}

如何将 HereIsTheQuestion::Type 编写成类似于原始 Struct 类型的数组元组?

谢谢, 米。

【问题讨论】:

    标签: c++ c++11 tuples variadic


    【解决方案1】:

    下面是HereIsTheQuestion 的实现方式。

    template<typename T>       //primary template
    struct HereIsTheQuestion;  //leave it undefined
    
    template<typename ...T>
    struct HereIsTheQuestion<std::tuple<T...>>  //partial specialization
    {
        using Type = std::tuple<std::vector<T>...>;
    };
    

    现在

    HereIsTheQuestion<std::tuple<int, float, char>>::Type
    

    std::tuple<std::vector<int>,std::vector<float>, std::vector<char>>
    

    希望对您有所帮助。

    【讨论】:

    • @spattija:是的,空元组将为::Type 产生空元组,即HereIsTheQuestion&lt;std::tuple&lt;&gt;&gt;::Type 将是std::tuple&lt;&gt;
    • 至于我的无知,我写了BlahBlah<...>::Type,你觉得有必要吗?我的意思是,可以 HereIsTheQuestion<...tuple...>::Type 替换为 HereIsTheQuestion<:tuple>> 吗? (没有内部 typedef,--> ::Type)?
    • @spattija:我不明白你在说什么。请在 ideone.com 上写下你的代码,并给我链接。
    • @spattija 使用类型别名,即template &lt;typename... T&gt; using HereIsTheQuestion_t = typename HereIsTheQuestion&lt;T...&gt;::type;
    【解决方案2】:

    您可以使用此模板来创建类型:

    namespace detail
    {
        template <typename... Ts>
        struct tuple_change { };
    
        template <typename... Ts>
        struct tuple_change<std::tuple<Ts...>>
        {
            using type = std::tuple<std::vector<Ts>...>;
        };
    }
    

    并像这样创建一个索引序列:

    namespace detail
    {
        template <int... Is>
        struct index { };
    
        template <int N, int... Is>
        struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
    
        template <int... Is>
        struct gen_seq<0, Is...> : index<Is...> { };
    }
    

    您还需要一个模板来允许打印元组:

    template <typename... Ts, int... Is>
    static void print(std::tuple<Ts...>& var, detail::index<Is...>)
    {
        auto l = { (print(std::get<Is>(var)), 0)... };
        (void)l;
    }
    
    template <typename... Ts>
    static void print(std::tuple<Ts...>& var)
    {
        print(var, detail::gen_seq<sizeof...(Ts)>{});
    }
    
    template <typename T>
    static void print(std::vector<T>& v)
    {
        for (auto a : v)
        {
            std::cout << std::boolalpha << a << std::endl;
        }
        std::cout << std::endl;
    }
    

    之后就变得简单了。这是你的程序:

    #include <iostream>
    #include <tuple>
    #include <vector>
    
    namespace detail
    {
        template <typename... Ts>
        struct tuple_change { };
    
        template <typename... Ts>
        struct tuple_change<std::tuple<Ts...>>
        {
            using type = std::tuple<std::vector<Ts>...>;
        };
    
        template <int... Is>
        struct index { };
    
        template <int N, int... Is>
        struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
    
        template <int... Is>
        struct gen_seq<0, Is...> : index<Is...> { };
    }
    
    template <typename... Args, int... Is>
    void fill(std::tuple<Args...>& var, detail::index<Is...>)
    {
        auto l = { (std::get<Is>(var).assign(5, 11), 0)... };
        // here I just decided to make the size 5
        (void)l;
    }
    
    template <typename... Args>
    void fill(std::tuple<Args...>& var)
    {
        fill(var, detail::gen_seq<sizeof...(Args)>{});
    }
    
    template <typename T>
    static void print(std::vector<T>& v)
    {
        for (auto a : v)
        {
            std::cout << std::boolalpha << a << std::endl;
        }
        std::cout << std::endl;
    }
    
    template <typename... Ts, int... Is>
    static void print(std::tuple<Ts...>& var, detail::index<Is...>)
    {
        auto l = { (print(std::get<Is>(var)), 0)... };
        (void)l;
    }
    
    template <typename... Ts>
    static void print(std::tuple<Ts...>& var)
    {
        print(var, detail::gen_seq<sizeof...(Ts)>{});
    }
    
    using result_type = detail::tuple_change<std::tuple<int, bool>>::type;
    
    int main()
    {
        result_type r;
    
        fill(r);
        print(r);
    }
    

    Demo

    【讨论】:

    • @spattija 你的意图是什么?你有三种不同的场景,我不确定你想要做什么。
    • @spattija 您不想将其更改为向量元组吗?这就是我在这里所做的。我还提供了一种通过演示打印元组的方法。
    猜你喜欢
    • 1970-01-01
    • 2013-12-06
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 2012-10-26
    • 1970-01-01
    • 2018-01-17
    • 2012-10-15
    相关资源
    最近更新 更多