`auto x = type {...}`初始化语法和`explicit`转换运算符 - clang vs gcc

Vit*_*meo 12 c++ explicit type-conversion language-lawyer c++17

鉴于此代码(在wandbox上):

struct X
{
    explicit operator int() { return 0; }
};

int main()
{
    auto y = int{X{}};
}
Run Code Online (Sandbox Code Playgroud)

以及以下编译器选项:

-std = c ++ 1z -Wall -Wextra -Wpedantic


  • g++ (经过测试的版本:7,6.1,5.3) 拒绝使用以下错误编译代码

    错误:初始化时无法将'X'转换为'int'

  • clang++ (测试版本:4,3.8,3.6) 愉快地编译了代码片段.


哪个编译器正在做正确的事情?

cppreference似乎表明auto var = type{...}语法应该触发显式转换.

小智 4

使用http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/n4606.pdf \n我认为 g++ 是错误的。

\n\n

8.6.4 第 3.7 条规定:

\n\n
\n

\xe2\x80\x94 否则,如果初始值设定项列表具有类型 E\n 的单个元素,并且 T 不是引用类型或其引用类型\n 与 E 引用相关,则对象或引用将从\n 初始化n 该元素(通过复制初始化进行复制列表初始化,或\n 通过直接初始化进行直接列表初始化);如果需要缩小转换(见下文)将元素转换为 T,则程序格式错误。

\n
\n\n

这意味着在这种非类类型的情况下使用直接 init,这导致我们看到 8.6 条款 17.7:

\n\n
\n

\xe2\x80\x94 否则,如果源类型是(可能是 cv 限定的)类\n 类型,则考虑转换函数。枚举了适用的转换函数(13.3.1.5),并通过重载决议选择最好的转换函数(13.3)。调用所选择的用户定义转换来将初始化表达式转换为正在初始化的对象。如果转换无法完成或不明确,则初始化格式错误。

\n
\n\n

最后 13.3.1.5 指出显式和隐式转换都被考虑用于直接初始化:

\n\n
\n

\xe2\x80\x94 考虑 S 及其基类的转换函数。\n 那些未隐藏在 S 中的非显式转换函数\n 并产生类型 T 或可以通过 a 转换为类型 T 的类型\n 标准转换序列 (13.3.3.1.1) 是候选函数。对于直接初始化,那些未隐藏在 S 中且产生类型 T 或可通过限定转换 (4.5) 转换为类型 T 的类型的显式转换函数也是候选函数。返回 cv 限定类型的转换函数被视为在选择候选函数的过程中产生该类型的 cv 非限定版本。返回 \xe2\x80\x9c 对 cv2 X\xe2\x80\x9d 的引用的转换函数返回左值或 x 值,具体取决于类型 \xe2\x80\x9ccv2 X\xe2\x80\x9d 的引用类型因此被认为在选择候选函数的过程中产生 X。

\n
\n