【问题标题】:Creating POD with variable number of elems创建具有可变数量元素的 POD
【发布时间】:2010-11-26 11:45:18
【问题描述】:

我想要一个类型,它实际上是 POD,但我希望能够指定其中的类型和类型,例如:

template<Args...>
struct POD
{
//here I would like to create depending on Args appropriate types as a members.
};

是否可以在 C++0x 中使用这个新的可变参数模板功能来做到这一点?

【问题讨论】:

    标签: templates c++11 variadic


    【解决方案1】:

    我从未使用过 C++0x 可变参数模板功能,但以下代码可在 G++ 4.5 上编译:

    template <typename... Args>
    struct tuple;
    
    template <typename T, typename... Args>
    struct tuple<T, Args...> {
        T value;
        tuple<Args...> inner;
    };
    
    template <typename T>
    struct tuple<T> {
        T value;
    };
    

    然而,初始化它们……很奇怪,因为我们需要嵌套内部值:

    int main() {
        tuple<int> n1 = { 23 };
        tuple<int, float> n2 = { 42, { 0.5f } };
        tuple<std::string, double, int> n3 = { "hello, world", { 3.14, { 97 } } };
    }
    

    检索值当然有点乏味。最简单的方法大概就是提供一个get&lt;N&gt;()函数模板。

    但是我们不能直接实现get,因为函数模板不能部分特化。要么我们需要使用 SFINAE(阅读:boost::enable_if),要么我们需要将 get 的实际功能委托给可以部分特化的类型。

    在下面,我做了后者。但首先,我们需要另一个辅助类型特征:nth_type,它返回 get 函数的适当返回类型:

    template <unsigned N, typename... Args>
    struct nth_type;
    
    template <unsigned N, typename T, typename... Args>
    struct nth_type<N, T, Args...> : nth_type<N - 1, Args...> { };
    
    template <typename T, typename... Args>
    struct nth_type<0, T, Args...> {
        typedef T type;
    };
    

    简单易行。只返回类型列表中的第 n 个类型。

    现在我们可以编写 get 函数了:

    template <unsigned N, typename... Args>
    inline typename nth_type<N, Args...>::type get(tuple<Args...>& tup) {
        return get_t<N, Args...>::value(tup);
    }
    

    就像我说的,这只是委派任务。没什么大不了的。在实践中,我们可能希望对 const 元组有另一个重载(但实际上我们会使用现有的 tuple 类型)。

    现在开始杀戮,然后是清淡的沙拉:

    template <unsigned N, typename... Args>
    struct get_t;
    
    template <unsigned N, typename T, typename... Args>
    struct get_t<N, T, Args...> {
        static typename nth_type<N, T, Args...>::type value(tuple<T, Args...>& tup) {
            return get_t<N - 1, Args...>::value(tup.inner);
        }
    };
    
    template <typename T, typename... Args>
    struct get_t<0, T, Args...> {
        static T value(tuple<T, Args...>& tup) {
            return tup.value;
        }
    };
    

    就是这样。我们可以通过在我们之前定义的变量中打印一些值来测试这一点:

    std::cout << get<0>(n1) << std::endl; // 23
    std::cout << get<0>(n2) << std::endl; // 42
    std::cout << get<0>(n3) << std::endl; // hello, world
    
    std::cout << get<1>(n2) << std::endl; // 0.5
    std::cout << get<1>(n3) << std::endl; // 3.14
    
    std::cout << get<2>(n3) << std::endl; // 97
    

    伙计,弄乱可变参数模板很有趣

    【讨论】:

    • 我非常确定组合成员必然是非 POD,从而使类型本身非 POD,因此我完全排除了这个解决方案 :)
    • 我相信有一个 std::tuple 也提供 get
    • @DeadMG:当然。这只是为了展示它是如何完成的,而不是创建生产代码。也就是说,std::tuple 是 POD 吗?
    • 注意事项: 当然,如果上面的tuple 类的每个模板参数都是 POD,则它只是一个 POD。第三个示例使用 std::string,因此不是 POD。
    • 如果它的所有参数都是 POD,那么是的。
    【解决方案2】:

    你熟悉std::tuple吗?

    AFAIK 如果它的所有成员都是 POD,它就是一个 POD,如果我错了,那么我猜这是不可能的。

    【讨论】:

      猜你喜欢
      • 2013-08-26
      • 2016-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多