I've made a Matrix
class with a constructor of this type:
Matrix<T>(const vector<vector<T>> &m)
If I do this I can instance a Matrix
object:
vector<vector<double>> a_v {
{ 17, 24, 1},
{ 23, 5, 7 },
{ 4, 6, 13 }
};
Matrix<double> a=a_v;
It works correctly, but I think that che constructor should be act as type converter and I think that also this code should work:
Matrix<double> a= {
{ 17, 24, 1},
{ 23, 5, 7 },
{ 4, 6, 13 }
};
However with this second code I get this error:
could not convert ‘{{17, 24, 1}, {23, 5, 7}, {4, 6, 13}}’ from 'brace-enclosed initializer list' to ‘Matrix’
Why C++11
does not convert the brace-enclosed initializer
to vector<vector<double>>
automatically?
What should I do if I want to initialize matrices in this way?
You have two options:
std::initializer_list<std::initializer_list<T>>
eclose the init expression with another set of {}
i.e.
Matrix<double> a{{
{ 17, 24, 1},
{ 23, 5, 7 },
{ 4, 6, 13 }
}};
Ok, I'll try a little explanation of what is going on here:
If there is no constructor taking a std::initializer_list
then the outermost {}
are always opening and closing the constructor call if you will, and not part of what you actually pass to the constructor.
Matrix<double> a{ {1, 2}, {3, 4} };
^ ^~~~~~~~~~~~~~ ^
| 2 parameters |
| |
| |
opening closing
As you can see this is taken as a constructor with 2 parameters, in this case 2 initializer_lists.
This is why you need another set of {}
:
Matrix<double> a{ {{1, 2}, {3, 4}} };
^ ^~~~~~~~~~~~~~~~ ^
| 1 parameter |
| |
| |
opening closing
In order for the outermost {}
to be considered an initializer_list then the constructor needs to have an overload taking a initializer_list
. That is what is happening in the std::vector
case.