空inizializer_list上的赋值运算符

use*_*358 5 c++ initializer-list overload-resolution compiler-bug visual-studio-2013

你能解释一下STL容器如何使用空的初始化列表处理赋值运算符?

当我做这样的事情:

vector<int> v;
v = { };
Run Code Online (Sandbox Code Playgroud)

被调用的函数不是:

vector& operator= (initializer_list<value_type> il);
Run Code Online (Sandbox Code Playgroud)

但:

vector& operator= (vector&& x);
Run Code Online (Sandbox Code Playgroud)

另一方面,当我和我自己的班级做类似的事情时:

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

/* ... */

A a;
a = { };
Run Code Online (Sandbox Code Playgroud)

代码不能在VS2013上编译,并说:

error C2593: 'operator =' is ambiguous
Run Code Online (Sandbox Code Playgroud)

如果列表不为空,它工作正常,它只是用初始化列表调用函数.只有当列表为空时才会出现问题,在向量上调用rvalue赋值运算符,在我的类上它会给出错误.

如何在向量和其他容器中处理这种情况?

Sha*_*our 3

这似乎是一个 bug clang( see it live ) 和 gcc( see it live ) 接受这个程序并选择看起来正确的std::initializer_list重载,因为这是完全匹配的,这在C++ 草案标准部分中有所介绍示例中的13.3.3.1.5 列表初始化序列第2段:

\n\n
void f(std::initializer_list<int>);\nf( {1,2,3} ); // OK: f(initializer_list<int>) identity conversion\nf( {\xe2\x80\x99a\xe2\x80\x99,\xe2\x80\x99b\xe2\x80\x99} ); // OK: f(initializer_list<int>) integral promotion\nf( {1.0} ); // error: narrowing\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们有一个完全匹配的身份转换

\n\n

对于参考重载,我们转到第5段,它说(重点是我的未来):

\n\n
\n

否则,如果参数是引用,请参见 13.3.3.1.4。[注:本节中的规则将适用于初始化底层临时以供参考。\xe2\x80\x94结束注]

\n
\n\n

表示创建了临时文件,然后我们可以将规则应用于生成的临时文件。这将是用户定义的转换,比完全匹配更糟糕。

\n\n

所以这不应该是含糊的。

\n\n

更新

\n\n

看起来有两个与此相关的活跃错误:

\n\n\n