采用 std::initializer_list 的构造函数优于其他构造函数

Constructor taking std::initializer_list is preferred over other constructors

我使用带有标志 -std=c++17 的 GCC 11.1.0 编译下面的代码。它发生在 stdout 上打印 initializer_list.

我用带有标志 -std=c++17 的 MSVC 编译了相同的代码,但它打印了“复制构造函数”。哪个编译器更符合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 };
}

对于这样的东西,编译器几乎从不“自由选择”。如果是这样,我们几乎无法编写任何可移植的 C++ 代码。

[over.match.list] does give priority to initializer_list constructors. Constructor function overloading under the rules of list initialization gets invoked at step 3.6。步骤 3.1-3.5 不适用,因为您的类型不符合任何这些情况。步骤 3.1 特别有趣,因为它专门用于调用复制构造函数而不是做其他事情,但它也仅适用于聚合。你的类型不是。

由于您的类型可以隐式转换为 int,并且您的类型采用 initializer_list<int>,因此有一种有效的方法可以构建与中类型的构造函数相匹配的 initializer_list题。因此,这是构造函数 [over.match.list] 将 select.

所以在这种情况下,VC++是错误的。正如is Clang,显然。