How to initialize all tuple elements by the same arguments?

The clearest way is just to construct each element in the tuple constructor argument list:

template <typename... TElements>
struct Container {
    Container(Foo foo, Bar bar)
        : tuple(TElements{foo, bar}...)
    {}
    std::tuple<TElements...> tuple;
};

This will result in move (or copy) constructing each element of the tuple from its corresponding constructor parameter; if this is unacceptable you could use piecewise construction:

template <typename... TElements>
struct Container {
    Container(Foo foo, Bar bar)
        : tuple(std::piecewise_construct, (sizeof(TElements), std::tie(foo, bar))...)
    {}
    std::tuple<TElements...> tuple;
};

Unfortunately in this case we have to do some kind of gymnastics (here sizeof and a comma operator) to get the variadic list TElements mentioned and ignored.


with double parameter pack expansion you can (try to) construct each element of a given tuple class with all given parameters to a function:

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)...);
}

And then somewhere in the code:

typedef std::tuple<NoDefault1, NoDefault2> myTuple;
auto t = construct_tuple<myTuple>(Foo{}, Bar{});

full working example: Link

Edit:

Since @Rakvan deleted his answer, I'll preserve the second (correct) part of it:

template <class ... Ts, class ... Args>
std::tuple<Ts...> cartesian_make_tuple(Args && ... args)
{
    return std::make_tuple(Ts{args...}...);
}

here is a working exaple

Tags:

C++

Tuples

C++11