我在下面用GCC11.1.0编译了这段代码,其中带有一个标志 -std=c++17
. 在标准输出上打印 initializer_list
.
我用带有标志的msvc编译了相同的代码 -std=c++17
但它打印了“复制构造函数”。哪个编译器更符合cpp标准?编译器可以自由选择一个构造函数吗?
# include <iostream>
using namespace std;
struct S
{
S(int) { }
S(initializer_list<int>) { cout << "initializer_list"; }
S(const S&) { cout << "copy constructor"; }
operator int() const { return 1; };
};
int main()
{
S s1(20);
S s2{ s1 };
}
1条答案
按热度按时间apeeds0o1#
对于这样的东西,编译器几乎从不“自由选择”。如果是这样,我们就不能编写任何可移植的C代码。
[over.match.list]确实优先考虑
initializer_list
构造器。在步骤3.6中调用列表初始化规则下的构造函数重载。步骤3.1-3.5不适用,因为您的类型不符合上述任何情况。步骤3.1特别有趣,因为它专门用于调用复制构造函数,而不是执行其他操作,但它也仅适用于聚合。你不是那种类型的。因为您的类型可以隐式转换为
int
,而且你的类型initializer_list<int>
,有一种有效的方法可以构建initializer_list
与所讨论类型的构造函数匹配的。因此,这是[over.match.list]将选择的构造函数。所以在这种情况下,vc是错误的。显然,叮当声也是如此。