【问题标题】:`auto x = type{...}` initialization syntax and `explicit` conversion operator - clang vs gcc`auto x = type{...}` 初始化语法和 `explicit` 转换运算符 - clang vs gcc
【发布时间】:2017-02-22 09:43:15
【问题描述】:

鉴于此代码(在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) 愉快地编译了sn-p


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

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

【问题讨论】:

  • FWIW,MSVC 也能顺利编译。
  • @Danh g++ 接受int y{X{}},如果只考虑隐式转换,则不应接受(因此要么这是错误的,要么是另一个错误)。

标签: c++ type-conversion language-lawyer c++17 explicit


【解决方案1】:

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

8.6.4 第 3.7 条规定:

——否则,如果初始化列表有一个类型为 E 的元素 并且 T 不是引用类型或其引用类型是 与 E 相关的引用,对象或引用从 该元素(通过复制列表初始化的复制初始化,或 通过直接列表初始化的直接初始化);如果一个 需要缩小转换(见下文)才能将元素转换为 T,程序格式错误。

这意味着在这种非类类型的情况下使用直接初始化,这将我们引向 8.6 第 17.7 节:

——否则,如果源类型是(可能是 cv 限定的)类 类型,转换函数被考虑。适用的换算 枚举函数(13.3.1.5),并选择最好的一个 通过重载决议(13.3)。用户自定义转换so 调用 selected 以将初始化表达式转换为 正在初始化的对象。如果转换无法完成或正在 模棱两可,初始化格式不正确。

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

——考虑 S 及其基类的转换函数。 那些不隐藏在 S 中的非显式转换函数 并产生类型 T 或可以通过 a 转换为类型 T 的类型 标准转换序列(13.3.3.1.1)是候选函数。 为 直接初始化,那些显式转换函数 不隐藏在 S 中并产生类型 T 或可以转换的类型 使用资格转换(4.5)键入 T 也是候选 功能。返回 cv 限定类型的转换函数是 考虑为此产生该类型的 cv 非限定版本 选择候选函数的过程。转换函数 返回“对 cv2 X 的引用”返回左值或 x 值,具体取决于 引用类型,类型为“cv2 X”,因此被认为是 为这个选择候选函数的过程产生 X。

【讨论】:

  • 在仔细阅读您发布的标准报价后,实际上在这种情况下g++ 似乎是错误的。我已经提交了bug #77976 并链接到这个问题和你的答案。谢谢!
  • 我想我已经找到了对这个错误的旧参考 - gcc.gnu.org/bugzilla/show_bug.cgi?id=63999
猜你喜欢
  • 1970-01-01
  • 2018-11-29
  • 1970-01-01
  • 1970-01-01
  • 2018-07-29
  • 2014-11-02
  • 1970-01-01
  • 2019-11-03
  • 1970-01-01
相关资源
最近更新 更多