Say, I have a 1-dimensional array encapsulated in a class named stA
class stA
{
public:
template<typename ... T>
stA(T ... t):
data_{t...}
{}
private:
int data_[2];
};
By taking advantage of variadic template , I can succeed in implementing this idea.
stA a = {1, 2};
But, when I tried to bring this trick to 2-dimensional-like class named stB
,
class stB
{
public:
template<typename ... T>
stB(T ... t):
data_{t...}
{}
private:
stA data_[2];
};
the trick failed.
stB b = {{1, 2}, {1, 2}};
error: could not convert '{{1, 2}, {1, 2}}' from brace-enclosed initializer list to 'stB' stB b = {{1, 2}, {1, 2}};
And this quite confuses to me at beginning.
Because if template-argument-deduction in stB::Ctor
results in T = const stA &
, then the Ctor
would become something like this,
stB(const stA & a, const stA & b):
data_{a, b}
{}
and of course stB b = {{1, 2}, {1, 2}};
would survive but with losing some flexibility in arguments.
After I had done some searching, I finally realized this may violate a rule of template argument deduction ,
Non-deduced contexts
6) The parameter P, whose A is a braced-init-list, but P is not std::initializer_list, a reference to one (possibly cv-qualified), or a reference to an array:
But I'm still wandering Is there still a way to get this idea happened and how?
The problem is that {1, 2}
is not an expression and only expressions can be deduced.
Option 1: use aggregate initialization. Make the data_
member public and aggregate initialization allows you to initialize the elements. Drawback: little control.
Option 2: use initializer_list
. As in:
class stA {
public:
stA(std::initializer_list<int> init):
data_{init.begin()[0], init.begin()[1]}
{
assert(init.size() == 2);
}
private:
int data_[2];
};
class stB {
public:
stB(std::initializer_list<std::initializer_list<int>> init):
data_{init.begin()[0], init.begin()[1]}
{
assert(init.size() == 2);
}
private:
stA data_[2];
};
Drawback: the size information is lost at compile time.
Option 3: use an aggregate type as constructor parameter.
class stA {
public:
stA(const int (&arr)[2]):
data_{arr[0], arr[1]}
{
}
private:
int data_[2];
};
class stB {
public:
stB(const int (&arr)[2][2]):
data_{arr[0], arr[1]}
{
}
private:
stA data_[2];
};
(This requires an extra pair of braces, as in stB b = {{{1, 2}, {3, 4}}};
.)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.