I have a situation where I have a templated class that contains a tuple. The elements must be initialized (they all have compatible constructor), but cannot be moved.
Simplified code showing the problem:
#include <tuple>
struct A {
int i{};
A(int i) : i(i) {}
// This causes a compile error in the tuple constructor:
A(A&&) = delete;
};
struct B {
int i{};
B(int i) : i(i) {}
B(B&& b) : i(b.i) {}
};
template <typename... Fs>
struct Container
{
std::tuple<Fs...> fields;
constexpr Container(int i) : fields(Fs{i}...) {}
};
int main()
{
Container<A, B> c{1};
}
However, when using a tuple directly, the move c'tor is not used. Instead I need a default constructor for the elements. This is however not possible in my situation. Also note that I cannot make the constructors of my elements constexpr
Now my main concern is calling a constructor on all elements when initializing a tuple. Is it possible to do this without a move constructor?
You might use a "dummy" template type which allows expansion as std::void_t
or std::type_identity
:
template <typename... Fs>
struct Container
{
std::tuple<Fs...> fields;
constexpr Container(int i) : fields((std::void_t<Fs>(), i)...) {}
};