【问题标题】:Variadic template constructor with multiple parameters packs具有多个参数包的可变参数模板构造函数
【发布时间】:2016-07-29 16:36:46
【问题描述】:

我已经阅读了thisthisthis 和许多其他内容......但这些帖子都没有回答或适用于我的具体问题。

我有一个带有可变参数模板构造函数的结构 X

struct X
{
    template<typename... T>
    X(T... t)   { /*...*/ }
};

我有一个结构Y,它包含两个X 类型的对象。我想为Y 定义一个模板构造函数,允许使用不同的参数列表正确初始化X 类型的两个成员,即看起来像下面的代码(显然不起作用):

struct Y
{
    template<typename... U, typename... V>
    Y(U&&... u, V&&... v)                                // this does not work
        : x1(std::forward(u)...), x2(std::forward(v)...) // this is was I need to do
        {}

    X x1, x2;
};

如何使用包装器、元组或任何合适的元编程机制来做到这一点?可以接受 C++14 解决方案。

【问题讨论】:

  • @πάντα ῥεῖ:我要的是 C++14;您链接的问题可能是我的问题的合适解决方案,但它已有 2 年历史了!也许有一个更好的使用 C++14。
  • 我不太确定 C++14 对 VTP 的解包有多大的改变,但是...
  • @πάντα ῥεῖ:你不确定?我很确定 C++14 为解包元组添加了一些有趣的新特性......
  • 哦,你现在重新标记了这个问题,所以我不能单枪匹马地重新打开它,抱歉。但这提供了重新开放至少得到其他 4 人确认的机会。给您点赞,以吸引更多评论者。
  • @πάνταῥεῖ 我投票决定重新开放,因为我认为问题和答案充其量是令人困惑的。

标签: c++ c++14 variadic-templates


【解决方案1】:

沼泽标准 index_sequence 技巧。

struct Y
{
private:
    template<typename... U, typename... V,
             std::size_t... UIs, std::size_t... VIs>
    Y(std::tuple<U...>&& u, std::tuple<V...>&& v,
      std::index_sequence<UIs...>, std::index_sequence<VIs...>)
        : x1(std::get<UIs>(std::move(u))...), 
          x1(std::get<VIs>(std::move(v))...)  
        {}
public:
    template<typename... U, typename... V>
    Y(std::tuple<U...> u, std::tuple<V...> v)
        : Y(std::move(u), std::move(v),
            std::index_sequence_for<U...>{},
            std::index_sequence_for<V...>{})
        {}

    X x1, x2;
};

在 C++17 中,只需使用 make_from_tuple:

struct Y
{
public:
    template<typename... U, typename... V>
    Y(std::tuple<U...> u, std::tuple<V...> v)
        : x1(std::make_from_tuple<X>(std::move(u))),
          x2(std::make_from_tuple<X>(std::move(v)))
        {}

    X x1, x2;
};

【讨论】:

  • 非常感谢,你的技巧很有效......除非我想传递对内部对象的引用 x1 & x2; (我尝试使用std::forward_as_tuple(),但这不起作用。)有没有办法修改你的代码,以便它可以使用引用元组? (我更新了我的问题以显示我需要的完美转发。)
  • 应该不需要任何修改。
  • 没错!我在参数列表上犯了错误。您的技巧也非常适合参考。非常感谢。
【解决方案2】:

使用元组是一个很大的开销,因为它已经要求 X 是可移动/可复制的,您可以直接使用该约束,并获得有史以来最易读的代码:

struct Y
{
    Y(X && _x1, X && _x2)                        
        : x1(std::move(_x1)), x2(std::move(_x2)) 
        {}

    X x1, x2;
};

在代码中只写:

Y y(X(args_x1...), X(args_x2...));

或者如果 X 有隐式构造函数:

Y y({args_x1...}, {args_x2...});

SampleCode

更有趣的问题是,如果 X 不可移动/可复制,但这超出了范围怎么办 ;)

【讨论】:

    猜你喜欢
    • 2019-06-04
    • 2018-05-18
    • 1970-01-01
    • 2016-09-02
    • 2015-05-06
    • 1970-01-01
    • 2019-01-29
    • 2016-01-02
    • 1970-01-01
    相关资源
    最近更新 更多