允许复制列表初始化和显式构造函数吗?

Copy list initialisation and explicit constructor allowed?

我在 VS2013 中使用以下代码并编译。

explicit QIcon(const QString &fileName); // file or resource name
void setWindowIcon(const QIcon &icon);

我这样调用函数:

setWindowIcon({ "icon.png" });

但是在 Clang 3.7.1 中它失败了:

error chosen constructor is explicit in copy-initialization

我在其他问题中读到,在 C++ 标准 §13.3.1.7 [over.match.list] 中,陈述如下:

In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed.

VS2013让这段代码编译是不是错了?

是的,VS2013 允许代码编译是错误的。

重要规则在[over.ics.list](引自N3337):

[over.ics.list]/1]: When an argument is an initializer list (8.5.4), it is not an expression and special rules apply for converting it to a parameter type.

[over.ics.list]/3]: Otherwise, if the parameter is a non-aggregate class X and overload resolution per 13.3.1.7 chooses a single best constructor of X to perform the initialization of an object of type X from the argument initializer list, the implicit conversion sequence is a user-defined conversion sequence. If multiple constructors are viable but none is better than the others, the implicit conversion sequence is the ambiguous conversion sequence. User-defined conversions are allowed for conversion of the initializer list elements to the constructor parameter types except as noted in 13.3.3.1.

13.3.3.1 概述隐式转换序列,其中引用 [class.conv.ctor] 关于用户定义的转换:

[class.conv.ctor]/1: A constructor declared without the function-specifier explicit specifies a conversion from the types of its parameters to the type of its class. Such a constructor is called a converting constructor.

因此如果构造函数应该用于这种形式的初始化,则不能标记为explicit