Reputation: 2135
This is the simplified code:
#include <vector>
class VInitList
{
public:
explicit VInitList(std::vector<int> v){}
};
int main()
{
VInitList vil({{}});
}
and compiling with g++ 5.2.1 a get this error:
error: call of overloaded ‘VInitList(<brace-enclosed initializer list>)’ is ambiguous
VInitList vil({{}});
^
main.cpp:6:5: note: candidate: VInitList::VInitList(std::vector<int>)
VInitList(std::vector<int> v){}
^
main.cpp:3:7: note: candidate: constexpr VInitList::VInitList(const VInitList&)
class VInitList
^
main.cpp:3:7: note: candidate: constexpr VInitList::VInitList(VInitList&&)
When I saw the compiler error I found out that I have written {{}}
by mistake (yeah, don't be mean to me), but I still cannot understand the error. IMHO either the compiler must get rid of the extra {} or return a syntax error.
Then I tried to compile this:
std::vector<int> v = {{{}}};
which works as intended.
Upvotes: 3
Views: 281
Reputation: 157314
But std::vector<int> v = {{{}}};
doesn't do what you think; it initializes a vector with one int
element, initialized to zero. This is because int
can be list-initialized:
int i{}; // assert(i == 0)
So std::vector<int> v = {{{}}};
is parsed as:
std::vector<int> v = {{{}}};
^-- int
^-- initializer_list<int>
^-- vector<int>
Likewise, if you write
VInitList vil{{{}}};
^-- int
^-- vector<int>
^-- VInitList
the contained vector<int>
has 1 element, initialized to zero. (The initializer_list<int>
stage can be omitted because the vector(initializer_list<int>)
constructor is non-explicit
).
So VInitList vil({{}});
could be parsed as:
VInitList vil({{}});
^-- int
^-- vector<int>
or as
VInitList vil({{}});
^-- vector<int>
^-- VInitList
In the first case the vector
has 1 element; in the second case it's empty. It's just as well that gcc rejects your code.
Clang only parses it as the former; I'm not sure which is correct.
Upvotes: 2