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

时间:2014-06-04 08:24:15

标签: c++ visual-c++ gcc c++11 clang

考虑以下代码:

#include <iostream>

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

  return 0;
}

  • 在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

      

问题:

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

  • 为什么上面提到的编译器应该表现出如此不同的行为?

1 个答案:

答案 0 :(得分:19)

答案

两个编译器都是正确的!


解释

标准没有区分错误警告,两者都属于诊断类别。

  

1.3.6 诊断消息 [defns.diagnostic]

     
    

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

  

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

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



gcc行为的原因?

有用的信息由@Jonathan Wakely通过对此帖的评论提供,以下是两条评论的合并;

  

他的确切原因是GCC在某一时刻犯了错误并且它打破了所有程序,所以它变成了警告。几个为大型C ++ 03代码库打开-std=c++0x选项的人发现了无害的缩小转换,导致大部分移植工作转到C ++ 11中。 PR 50810 Alisdair报告缩小错误的比例大约是Bloomberg代码库中95%的问题。

在同样的公关中你可以看到,不幸的是它不是&#34;让我们发出警告并完成警告&#34;因为为了获得正确的行为需要花费很多时间。