简体   繁体   中英

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.

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.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM