assignment operator on empty inizializer_list

2019-06-20 17:33发布

问题:

can you explain how STL containers handle assignment operator with empty initializer list?

when i'll do something like this:

vector<int> v;
v = { };

the function that is called is not:

vector& operator= (initializer_list<value_type> il);

but:

vector& operator= (vector&& x);

on the other hand, when i'll do something similar with my own class:

struct A {
    A& operator= (const A&) { return *this; }
    A& operator= (A&&) { return *this; }
    A& operator= (initializer_list<int>) { return *this; }
};

/* ... */

A a;
a = { };

the code does not compile on VS2013, and says:

error C2593: 'operator =' is ambiguous

if the list is not empty, it works fine, it just calls the function with initializer list. the problem appears only when the list is empty, on vector it calls the rvalue assignment operator, on my class it gives error.

how this situation is handled in vector and other containers?

回答1:

This appears to be a bug clang(see it live) and gcc(see it live) accept this program and choose the std::initializer_list overload which looks correct since that is an exact match, this is covered in the C++ draft standard section section 13.3.3.1.5 List-initialization sequence paragraph 2 from the example:

void f(std::initializer_list<int>);
f( {1,2,3} ); // OK: f(initializer_list<int>) identity conversion
f( {’a’,’b’} ); // OK: f(initializer_list<int>) integral promotion
f( {1.0} ); // error: narrowing

we have an identity conversion which is an exact match.

For the reference overloads we go to paragraph 5 it says (emphasis mine going forward):

Otherwise, if the parameter is a reference, see 13.3.3.1.4. [ Note: The rules in this section will apply for initializing the underlying temporary for the reference. —end note ]

indicates that temporary is created an then we can apply the rules to resulting temporary. This will be a User-defined conversion which is worse than an exact match.

So this should not be ambiguous.

Update

Looks like there are two active bugs related to this:

  • Compiler confused about whether to use a initializer_list assignment operator
  • VC++ 12 RC fails to choose between initializer_list enabled assignment operator and canonical one for std::pair list elements