C++ 如何用相同的参数初始化所有元组元素?

C++ 如何用相同的参数初始化所有元组元素?,c++,c++11,tuples,C++,C++11,Tuples,是否可以使用基础类型的非默认构造函数,通过相同的参数初始化std::tuple的所有元素 template <typename... TElements> struct Container { // I'd wish to be able to do something like this: Container(Foo foo, Bar bar) : tuple(foo, bar) {} std::tuple<TElements.

是否可以使用基础类型的非默认构造函数,通过相同的参数初始化
std::tuple
的所有元素

template <typename... TElements>
struct Container {
    // I'd wish to be able to do something like this:
    Container(Foo foo, Bar bar)
        : tuple(foo, bar)
    {}
    std::tuple<TElements...> tuple;
};
模板
结构容器{
//我希望能够做到以下几点:
容器(Foo-Foo,Bar-Bar)
:元组(foo,bar)
{}
std::tuple;
};

关键是我不知道元组的大小(它是由一个可变参数模板化的),所以我不能根据需要多次复制参数。我只知道
telement
中的所有类型都有一个以
Foo
Bar
为参数的构造函数,并且没有默认的构造函数。

通过双参数包扩展,您可以(尝试)用所有给定参数构造给定元组类的每个元素到一个函数:

template <class T> struct tuple_construct_t;

template <class... Ts> struct tuple_construct_t<std::tuple<Ts...>> {
  template <class... Args>
  static std::tuple<Ts...> make_tuple(Args&&... args) {
    //this is the central part - the double pack expansion
    return std::make_tuple(Ts{args...}...);
  }
};

// a little free helper function...
template <class Tup, class... Args>
Tup construct_tuple(Args&&... args) {
    return tuple_construct_t<Tup>::make_tuple(std::forward<Args>(args)...);
}
template struct tuple\u construct\t;
模板结构元组构造{
模板
静态std::tuple make_tuple(Args&&…Args){
//这是中心部分-双包扩展
返回std::make_tuple(Ts{args…}…);
}
};
//一个小的免费助手函数。。。
模板
元组构造\u元组(Args&&…Args){
返回元组(std::forward)

编辑:

既然@Rakvan删除了他的答案,我将保留第二部分(正确的):

template <class ... Ts, class ... Args>
std::tuple<Ts...> cartesian_make_tuple(Args && ... args)
{
    return std::make_tuple(Ts{args...}...);
}
模板
std::tuple笛卡尔生成tuple(Args&&…Args)
{
返回std::make_tuple(Ts{args…}…);
}

我们想进行变量扩展(以获得恰到好处的参数数量),但我们必须给出一个“提示”,将扩展绑定到我们想要匹配的包:

template<typename Dummy, typename Value>
Value depends(Value&& value)
{ return std::forward<Value>(value); }

template<typename... Elements>
void example()
{
    // naive attempt to construct all the elements from 0:
    // std::tuple<Elements...> t { 0... };

    // now expansion is tied to the Elements pack
    std::tuple<Elements...> t { depends<Elements>(0)... };

    // with two arguments:
    std::tuple<Elements...> t { { depends<Elements>(0), depends<Elements>(1) }... };
}
模板
值取决于(值和值)
{return std::forward(value);}
模板
void示例()
{
//试图从0构造所有元素的幼稚尝试:
//std::元组t{0…};
//现在扩展绑定到元素包
std::tuple t{dependens(0)…..};
//有两个论点:
元组t{{依赖(0),依赖(1)}…};
}

最清晰的方法就是构造
元组中的每个元素
构造函数参数列表:

template <typename... TElements>
struct Container {
    Container(Foo foo, Bar bar)
        : tuple(TElements{foo, bar}...)
    {}
    std::tuple<TElements...> tuple;
};
模板
结构容器{
容器(Foo-Foo,Bar-Bar)
:元组(远程元素{foo,bar}…)
{}
std::tuple;
};
这将导致move(或copy)从其相应的构造函数参数构造元组的每个元素;如果这是不可接受的,则可以使用分段构造:

template <typename... TElements>
struct Container {
    Container(Foo foo, Bar bar)
        : tuple(std::piecewise_construct, (sizeof(TElements), std::tie(foo, bar))...)
    {}
    std::tuple<TElements...> tuple;
};
模板
结构容器{
容器(Foo-Foo,Bar-Bar)
:元组(std::分段_构造,(sizeof(TElements),std::tie(foo,bar))…)
{}
std::tuple;
};

不幸的是,在这种情况下,我们必须做一些练习(这里是
sizeof
和一个逗号运算符),以得到提到并忽略的变量列表
telement

std::tuple foo{{{{foo},Bar{},{foo{},Bar{};
?@Jarod42:我想重点不在于重复这些参数。我不能明确地这样写,因为我不知道元组的大小。控制元组大小的模板参数是什么?我编辑了我的问题,以便更清楚地描述我的问题。对不起,我不小心编辑了你的答案而不是我的答案。@Rakvan的第二个答案r似乎是正确的,这是最简单的!@lizarisk是的,我刚刚意识到你不能转发参数,因为你不应该用同一个转发(移动)的右值参数构造多个元组元素。哇,它真的那么简单,我怎么会错过它呢?:)@变量模板通常比你想象的要简单:)@0x499602D2我们需要重复
std::tie(foo,bar)
元组中元素的数量与元组中元素的数量一样多,因此我们需要扩展
telement
,但实际上我们并不需要每个元素的类型,因此我们必须找到忽略它的方法。只是一个小小的补充:我使用了您的方法(谢谢!)使用gcc6并得到一个逗号运算符左侧参数无效的警告。为了消除该警告,我将
sizeof(TElements)
包装到一个cast中,以
void
(void(sizeof(TElements)),std::tie(foo,bar))
template <typename... TElements>
struct Container {
    Container(Foo foo, Bar bar)
        : tuple(std::piecewise_construct, (sizeof(TElements), std::tie(foo, bar))...)
    {}
    std::tuple<TElements...> tuple;
};