缩小转换和初始化列表,哪个编译器是正确的?

101*_*010 22 c++ gcc clang visual-c++ c++11

考虑以下代码:

#include <iostream>

auto main() -> int {
  double x(7.0);
  int i{x};
  std::cout << "i = " << x << std::endl;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)
  • 在GCC4.9中编译时,只有一个警告编译好:

    warning: narrowing conversion of ‘x’ from ‘double’ to ‘int’ inside { }


  • 使用Clang3.3或VC++ 2013进行编译会产生编译错误:

    error: type 'double' cannot be narrowed to 'int' in initializer list error C2397: conversion from 'double' to 'int' requires a narrowing


问题:

  • 根据标准,哪个编译器是正确的?

  • 上面提到的编译器是否应该表现出这种多样化的行为?

Fil*_*efp 19

答案

两个编译器都是正确的!


说明

标准不区分错误警告,都属于诊断类别.

1.3.6 诊断信息 [defns.diagnostic]

属于实现定义的实现输出消息子集的消息

由于标准规定在程序格式错误时需要进行诊断,例如在支撑初始化器内发生缩小转换时,两个编译器都在确认.

即使程序从标准的角度来看是不正确的,它也不要求编译器因此而停止编译; 只要它发出诊断,实现就可以随心所欲地做任何事情.



gcc行为的原因是什么?

有用的信息由@Jonathan Wakely通过对这篇文章的评论提供,下面是两条评论的合并;

他确切的理由是GCC在某一时刻犯了错误,它打破了所有的程序,所以它变成了警告.几个打开-std=c++0x大型C++ 03代码库选项的人发现了无害的缩小转换,导致大部分移植工作都转到了C++ 11.

例如,参见PR 50810,其中Alisdair报告缩小错误是彭博中95%以上的问题代码库.

在同一个公关中你可以看到,不幸的是,这不是"让我们发出警告并完成它"的情况,因为它需要花费大量的时间才能获得正确的行为.

  • +1确切的原因是GCC在某一时刻犯了错误,它打破了**所有程序**所以它变成了警告.几个为大型C++ 03代码库打开`-std = c ++ 0x`选项的人发现无害的缩小转换导致大部分移植工作转到C++ 11,例如`for(int i = 0) ; i <10; ++ i)char c [] = {'f','o','o','0'+ i,'\ 0'};`其中值永远不会超出范围,但是在技​​术上是一个缩小的转换 (16认同)
  • 参见例如[PR 50810](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50810),其中Alisdair报告缩小错误是彭博代码库中95%以上的问题(在同一个PR中你可以看出,不幸的是,这不是_的情况"让我们发出警告并完成它"_因为需要花费大量的时间才能获得正确的行为) (2认同)