缩小从`int`(常量表达式)到`unsigned int`的转换 - MSVC vs gcc vs clang

Vit*_*meo 9 c++ type-conversion visual-c++ language-lawyer c++11

constexpr int i = 100;
struct F { F(unsigned int){} };
int main() { F{i}; }
Run Code Online (Sandbox Code Playgroud)

上面的代码:

  • 编译没有警告g++ 7-Wall -Wextra -Wpedantic.

  • 编译没有警告clang++ 4-Wall -Wextra -Wpedantic.

  • 无法编译MSVC 2017:

    从'const int'转换为'unsigned int'需要缩小转换

问:这是MSVC错了吗?

godbolt.org上的实例


int i = 100;
struct F { F(unsigned int){} };
int main() { F{i}; }
Run Code Online (Sandbox Code Playgroud)
  • 编译带有警告g++ 7-Wall -Wextra -Wpedantic:

    缩小'i'从'int'到'unsigned int'的转换

  • 编译失败clang++ 4-Wall -Wextra -Wpedantic:

    在初始化列表中,非常量表达式不能从类型'int'缩小到'unsigned int'

  • 无法编译MSVC 2017:

    从'const int'转换为'unsigned int'需要缩小转换

问:这里的g ++错了吗?(即它应该产生硬错误吗?)

godbolt.org上的实例

Yak*_*ont 4

从来不要求任何 C++ 程序产生硬错误。打印诊断有要求。标准未指定诊断的形式:一个老笑话是,打印出单个空格即可满足标准的诊断要求。这将是一个实施质量问题。

有一些格式不正确的程序,标准对其行为没有限制,有时甚至是强制性的诊断。

在某些情况下,程序格式不正确,需要进行诊断。处理该问题的一种方法是生成一条消息,指出这是一个错误,然后不生成任何要运行的二进制文件。另一种方法是生成一条消息,说明这是一条警告,然后生成可以运行的二进制文件。

因此,g++ 在标准下仅仅打印出警告并没有错。

从技术上讲,生成的程序都是未定义的行为;g++ 可以在运行时格式化您的硬盘,而不会违反标准。这将被视为实施质量问题。

沙菲克的回答涵盖了第一个问题。 i是常量表达式,其值符合目标类型;不应有关于缩小转换的警告或错误。

C++ 标准并不能保护您免受恶意编译器的侵害。

据报道,-pedantic-errors当标准要求生成的程序格式不正确时,可以传递给 g++ 以使其生成硬错误而不是警告。