I am trying to pass multiple initializer lists through a variadic template to construct an std::array in place.
However I fail to find a version that compiles (C++17).
Consider the following code:
struct TwoInts {
TwoInts(int x, int y)
: a{x}
, b{y}
{}
int a,b;
};
template<typename T, int S>
struct Holder {
template<typename... Args>
Holder(Args&&... args) : m({{std::forward<Args>(args)...}}) {}
//Deleted for clarity of the example:
Holder(const Holder& o) = delete;
Holder(Holder&& o) = delete;
std::array<T,S> m;
};
We can perform the following initializations:
TwoInts a = {1,2};
std::array<TwoInts,1> b{{{1,2}}};
std::array<TwoInts,2> c{{{1,2},{3,4}}};
Holder<int,1> d{1};
Holder<int,2> e{1,2};
But how to modify the example to make this work?
Holder<TwoInts,1> f{{{1,2}}};
Holder<TwoInts,2> f{{{1,2},{3,4}}};
Gcc and clang fail find a matching constructor.
You can be explicit about the argument types instead of implicitly passing std::initializer_list
s:
Holder<TwoInts,1> f{TwoInts{1, 2}};
Holder<TwoInts,2> e{TwoInts{1,2}, TwoInts{3,4}};
This is due to std::initializer_list
s that produce a so-called "non-deduced" context, so you cannot use std::initializer_list
s to pass them to a template constructor (as the language doesn't allow you to explicitly nail down the template types of a constructor template).
Note that in std::array<TwoInts,1> b{{{1,2}}};
you don't use std::initializer_list
, but instead perform aggregate initialization, and in Holder<int,1> d{1};
, you just pass an int
, which works fine with deduction.
If TwoInt
objects aren't move/copy constructible, you could turn them into an aggregate;
struct TwoInts {
TwoInts(const TwoInts&) = delete;
TwoInts(TwoInts&&) = delete;
int a,b;
};
and then use aggregate initialization throughout. The holder constructor should look like this;
template<typename... Args>
Holder(Args&&... args) : m{{std::forward<Args>(args)...}} {}
// ^ no parentheses ... neither ^
and you can initialize with
Holder<TwoInts,1> f{1, 2};
Holder<TwoInts,2> e{1,2, 3,4};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With