Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constructor, initializer list and different behaviour in g++ and clang

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.

like image 749
FrankS101 Avatar asked Dec 12 '25 09:12

FrankS101


1 Answers

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.

like image 61
ecatmur Avatar answered Dec 14 '25 21:12

ecatmur



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!