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

Mic*_*hal 11 c++ constructor initializer-list language-lawyer c++17

我用带有标志的 GCC 11.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 };
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*las 13

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

[over.match.list]确实优先考虑initializer_list构造函数。列表初始化规则下的构造函数重载在步骤 3.6被调用。步骤 3.1-3.5 不适用,因为您的类型不符合任何这些情况。步骤 3.1 特别有趣,因为它专门用于调用复制构造函数而不是做其他事情,但它也仅适用于聚合。你的类型不是。

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

所以在这种情况下,VC++是错误的。由于是锵,显然。