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

时间:2017-03-28 17:28:37

标签: c++ c++11 visual-c++ type-conversion language-lawyer

constexpr int i = 100;
struct F { F(unsigned int){} };
int main() { F{i}; }

上面的代码段:

  • 使用g++ 7-Wall -Wextra -Wpedantic上编译,但没有任何警告

  • 使用clang++ 4-Wall -Wextra -Wpedantic上编译,但没有任何警告

  • 无法在MSVC 2017上编译:

      

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

问:这里的MSVC错了吗?

live example on godbolt.org

int i = 100;
struct F { F(unsigned int){} };
int main() { F{i}; }
  • 使用g++ 7-Wall -Wextra -Wpedantic上编译带有警告的

      

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

  • 无法使用clang++ 4编译-Wall -Wextra -Wpedantic

      在初始化列表中,

    非常量表达式不能从“int”类型缩小为“unsigned int”

  • 无法在MSVC 2017上编译:

      

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

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

live example on godbolt.org

1 个答案:

答案 0 :(得分:4)

永远不要求任何C ++程序产生硬错误。有打印诊断的要求。诊断的形式没有通过标准规定:一个古老的笑话是打印出单个空间满足标准的诊断要求。这将是一个实施质量问题。

标准不完整的程序标准对其行为没有任何限制,有时也是强制性诊断。

有些程序格式错误且需要诊断。处理它的一种方法是产生一条消息,说明它是一个错误,然后不生成任何二进制文件来运行。另一种方法是生成一条消息,说明它是一个警告,然后生成一个可以运行的二进制文件。

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

结果程序在技术上是所有未定义的行为; g ++可以在运行时格式化您的硬盘而不违反标准。这将被视为实施质量问题。

Shafik's answer here涵盖了第一个问题。 i是常量表达式,其值适合目标类型;关于缩小转换应该没有警告或错误。

C ++标准并不能保护您免受恶意编译器的攻击。<​​/ p>

据报道,-pedantic-errors可以传递给g ++,以便在标准规定生成的程序格式错误时生成硬错误而不是警告。