Reputation: 463
I have 2 constructors in struct 'matrix'.
matrix(const unsigned int m, const unsigned int n);
matrix(const std::vector<std::vector<double>> &elements);
When I call it like this
matrix mat({{1},{1}});
It throws error
call of overloaded ‘matrix(<brace-enclosed initializer list>)’ is ambiguous
note: candidate: matrix::matrix(const std::vector<std::vector<double> >&)
note: candidate: matrix::matrix(const matrix&)
So, it thinks, that {{1},{1}} - is 'matrix' object, but how?
Upvotes: 3
Views: 1261
Reputation: 67802
So, it thinks, that {{1},{1}} - is 'matrix' object, but how?
In your sample code
matrix mat({{1},{1}});
you explicitly told the compiler to try and match that expression to a matrix
constructor.
It doesn't "think" the expression {{1},{1}}
is a matrix, it's trying to make it into one, because you asked it to.
As for why you get the error (which isn't what you asked, but seems worth mentioning), it's because
vector<double> v{1};
is a valid declaration of a vector with a single value (1.0), and so
vector<vector<double>> vv{{1},{1}};
is also a valid declaration of a vector containing two element vectors, each with a single double
element of value 1.0, and so finally
mat{{{1},{1}}};
would be a valid match for the vector constructor. Since this conversion is allowed implicitly, we're allowed to rewrite
mat m({{1},{1}});
as
mat m(mat{{{1},{1}}});
and hence the ambiguity. Note the round and curly brackets carefully.
You can either make the constructor implicit, or just get used to uniform initialization style and write
mat m{{{1},{1}}};
in the first place.
Upvotes: 5
Reputation: 93344
When calling matrix mat({{1},{1}})
the compiler finds these two ambiguous construction paths:
Call the vector<vector>>
constructor by constructing two vectors with one elements inside a vector.
Implicitly create a temporary matrix with the first constructor, then construct mat
with that temporary.
Create a temporary matrix from matrix(const unsigned int m, const unsigned int n)
. (The first {1}
is matched to m
, the second {1}
is matched to n
.)
Try to construct mat
from the temporary by using matrix(const matrix&)
.
Marking the first (or both) constructor(s) as explicit
will unambiguously make matrix mat({{1},{1}})
invoke the...
matrix(const std::vector<std::vector<double>> &elements);
...one.
Upvotes: 3