' auto x = type{…} '初始化语法和'显式'转换操作符- clang vs gcc

`auto x = type{...}` initialization syntax and `explicit` conversion operator - clang vs gcc

本文关键字:转换 显式 操作符 clang gcc vs auto type 初始化 语法      更新时间:2023-10-16

给定此代码(on wandbox):

struct X
{
    explicit operator int() { return 0; }
};
int main()
{
    auto y = int{X{}};
}

和以下编译器选项:

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


  • g++ (测试版本:7、6.1、5.3)拒绝编译代码,出现以下错误

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

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


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

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

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

8.6.4第3.7条规定:

—否则,如果初始化列表中只有一个E类型的元素要么T不是引用类型,要么它的引用类型是与E相关的引用,初始化的对象或引用该元素(通过copy-initialization for copy-list-initialization),或者通过直接初始化(直接列表初始化);如果一个需要缩小转换(见下文)来将元素转换为T,程序是病态的。

意味着在非类类型的情况下直接使用init,这导致了8.6第17.7条:

-否则,如果源类型是一个(可能是cv限定的)类考虑类型、转换函数。适用的转换函数被枚举(13.3.1.5),并选择最好的函数通过重载解析(13.3)。用户定义的转换方法将初始化式表达式转换为正在初始化的对象。如果转换不能完成或正在进行歧义,初始化是病态的。

最后13.3.1.5声明直接初始化考虑显式和隐式转换:

-考虑S及其基类的转换函数。那些没有隐藏在S中的非显式转换函数并产生类型T或可通过a转换为类型T的类型标准转换序列(13.3.3.1.1)是候选函数。,直接初始化,那些显式的转换函数不隐藏在S中,生成类型T或可转换的类型到类型T的限定转换(4.5)也是候选的函数。返回cv限定类型的转换函数是被认为为this生成该类型的cv-不限定版本选择候选函数的过程。转换函数返回"对cv2 X的引用"返回左值或xvalue,取决于引用类型为"cv2 X",因此被认为是在选择候选函数的过程中,yield X。