为什么将显式构造视为(隐式)变窄转换?

问题描述 投票:2回答:3

请考虑以下代码:

uint32_t foo(uint64_t x ) {
    auto y = uint32_t { x };
    return y;
}

[这被认为是编译器迫于警告我(GCC 9)甚至声明一个错误(clang 9):GodBolt

我的问题:

  1. 为什么uint32_t { x }不如static_cast<uint32_t>(x)明确?
  2. 为什么用clang比使用GCC更严重,会出错?
c++ g++ language-lawyer clang++ narrowing
3个回答
3
投票

为什么uint32_t { x }不如static_cast<uint32_t>(x)明确?

这不是很明确,只是不允许。直接或复制列表初始化时,不允许缩小转换。当您执行auto y = uint32_t { x };时,您正在使用缩小的转换范围对y进行直接列表初始化。 (保证复制省略意味着这里不再有临时的内容)

为什么用clang比使用GCC更严重,会出错?

由实施者决定。显然clang想要更严格并发出一个硬错误,但两者都很好。该标准仅要求给出诊断消息,并包含警告或错误信息。


2
投票

添加到@NathanOliver的答案-如果我们这样构造32位整数,警告和错误就会消失:

uint32_t foo(uint64_t x ) {
    auto y = uint32_t(x);
    return y;
}

所以,这里的(x){x}在语义上不是等效的(即使同一个构造函数最终被调用,如果它是一个类)。该标准中的不缩窄保证显然仅适用于列表初始化IIANM。

因此,如果要格外小心(或者如果不想打扰,请加上括号,这是使用花括号初始化的动机。)>


© www.soinside.com 2019 - 2024. All rights reserved.