c++c++11tuples

How to initialize all tuple elements by the same arguments?


Is it possible to initialize all elements of std::tuple by the same argument, using the non-default constructors of the underlying 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 point is that I don't know the tuple size (it's templated by a variadic parameter), so I can't duplicate the arguments as many times as I need. The only thing I know is that all types in TElements have a constructor taking Foo and Bar as arguments and don't have a default constructor.


Solution

  • 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.