How to initialize all elements of a tuple by the same arguments?

Is it possible to initialize all std::tuple elements with the same argument, using non-default constructors for base types?

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

The fact is that I do not know the size of the tuple (it was changed by the variational parameter), so I can not duplicate the arguments as many times as I need. The only thing I know is that all types in TElements have a constructor that takes Foo and Bar as arguments and does not have a default constructor.

+7
c ++ c ++ 11 tuples
source share
3 answers

The easiest way is to build each element in the argument list of the tuple constructor:

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

This will lead to a move (or copy) of the construction of each element of the tuple from its corresponding constructor parameter; if this is unacceptable, you can use a piecewise construct:

 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 the comma operator) to get the mentioned and ignored variational list of TElements .

+9
source share

with a package extension with two parameters, you can (try) to build each element of a given tuple with all the given function parameters:

 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 will save 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 the workflow

+3
source share

We want to make a variational extension (in order to get only the right number of parameters), but we need to put a "hint to associate the extension with which package we want to map:

 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) }... }; } 
+2
source share

All Articles