具有多个参数包的可变模板构造函数

Variadic template constructor with multiple parameters packs

本文关键字:构造函数 参数      更新时间:2023-10-16

我读过这个、这个、这个和许多其他。。。但这些帖子都没有回答或适用于我的具体问题。

我有一个带有可变模板构造函数的结构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解决方案是可以接受的。

转向架标准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;
};

使用元组是一个很大的开销,因为它已经要求from 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...});

样本代码

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