Search code examples
c++stdtupleparameter-pack

Construct a tuple by passing a the same variable number of constructor arguments to each element


I am trying to construct a tuple by passing the same constructor arguments to each element.

For illustrative purposes, I have 2 classes which can take any number of constructor arguments:

struct Foo
{
    template<typename... Args>
    Foo(Args... args)
    {
      std::cout << "Foo " << (... << args) << '\n';
    }
};

struct Bar
{
    template<typename... Args>
    Bar(Args... args)
    {
      std::cout << "Bar " << (... << args) << '\n';
    }
};

I have a Storage class which contains a std::tuple of a variable number of objects; I want to pass the same constructor arguments to each object.

Single argument case (works):

Similar to this question, I have been able to pass a single constructor argument to each object:

template<typename... Ts> 
struct Storage
{
    template<typename Arg>
    Storage(Arg arg) : storage((sizeof(Ts), arg)...) {} // passes 'arg' to each object

    std::tuple<Ts...> storage;
};

This works, as illustrated here (godbolt):

Storage<Foo, Bar> s("hello world");

Output:

Bar hello world
Foo hello world

Extend to multiple constructor arguments (does not work):

I need to pass a variable number of arguments to Storage, but so far I cannot work out how to unpack the two different parameter packs

Initial attempts:

template<typename... Args>
Storage(Args... args) : storage((sizeof(Ts), args)...) {}
error: mismatched argument pack lengths while expanding ‘(sizeof (Ts), args)’
|     Storage(Args... args) : storage((sizeof(Ts), args)...) {}
|                                                          ^
template<typename... Args>
Storage(Args... args) : storage((sizeof(Ts), args...)...) {}
error: expected binary operator before ‘)’ token
|     Storage(Args... args) : storage((sizeof(Ts), args...)...) {}
|                                                         ^

Question:

Is it possible to construct a variadic tuple by passing a the same variable number of constructor arguments?

template<typename... Ts> 
struct Storage
{
    template<typename... Args>
    Storage(Args... args) : storage(/* what goes here? */) {}

    std::tuple<Ts...> storage;
};

Solution

  • It would be:

    template <typename... Args>
    Storage(Args... args) : storage(Ts(args...)...) {}