首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >初始化列表缩小时g++4.9和g++5的不同行为

初始化列表缩小时g++4.9和g++5的不同行为
EN

Stack Overflow用户
提问于 2015-02-11 22:48:47
回答 2查看 563关注 0票数 4

请考虑以下代码:

代码语言:javascript
复制
#include <iostream>

int main()
{
    int i{10.1}; // narrowing, should not compile
    std::cout << i << std::endl;
}

根据C++11标准,它不应该编译(禁止在大括号初始化中缩小范围)。

现在,使用g++4.9.2 -std=c++11编译只会发出警告

代码语言:javascript
复制
warning: narrowing conversion of '1.01e+1' from 'double' to 'int' inside { } [-Wnarrowing]

移除-std=c++11标志将导致关于大括号init的警告,但不会导致任何缩窄:

代码语言:javascript
复制
warning: extended initializer lists only available with -std=c++11 or -std=gnu++11

另一方面,g++5 不编译,前提是使用g++5 -std=c++11进行编译。但是,如果省略了-std=c++11,那么即使是g++5也会愉快地编译它,只给出一个与大括号init相关的警告,而不是对缩窄的警告:

代码语言:javascript
复制
warning: extended initializer lists only available with -std=c++11 or -std=gnu++11

上面的行为似乎是错误的,g++4.9不应该编译代码,如果您忘记指定-std=c++11,那么g++5编译它就更奇怪了。这是一个已知的问题吗?

EN

回答 2

Stack Overflow用户

发布于 2015-02-11 23:25:02

{}内部的缩窄转换只是C++11模式中的错误的原因很简单:它不是C++03中的错误。现在,T var{value};是新的C++11语法,但是T var = {value};已经是有效的C++03语法,并且确实允许收缩转换。

代码语言:javascript
复制
int i = { 10.1 }; // valid C++03, invalid C++11

这使得GCC开发人员更容易在T var{value};T var={value};初始化中同样处理缩小转换。这很有用,因为它避免了编译器中警告的两个单独的代码路径。

这使得GCC开发人员更容易接受T var{value};模式下的C++03语法,只需对其进行警告。其他几个C++11语法扩展也在C++03模式下启用。这很有用,因为GCC在标准库的实现中使用了几个C++11语法扩展(在这里,有关它的警告被禁止)。

int i{10.1};不是GCC 4.9在C++11模式下的一个错误,而是GCC 5中的一个错误,原因是没有将它作为一个错误来处理,导致了有效代码被拒绝。C++标准要求将其视为SFINAE上下文中的一个错误,下面是一个有效的C++11程序,由于GCC 4.9的原因,程序运行不正确:

代码语言:javascript
复制
#include <stdio.h>
template <typename T> void f(double) { puts("ok"); }
template <typename T, typename = decltype(T{10.1})> void f(int) { puts("error"); }
int main() { f<int>(1); }

这个应该印上"ok“。第二个过载应该被丢弃。

使用GCC 4.9,它打印“错误”,因为第二个重载不会被丢弃,而且intdouble更匹配。

票数 9
EN

Stack Overflow用户

发布于 2015-02-11 23:17:37

引用1.4 [intro.compliance]

符合规范的实现可能有扩展(包括附加的库函数),只要它们不改变任何格式良好的程序的行为。根据本国际标准,实现需要诊断使用此类扩展的程序,这些扩展的格式不正确。但是,这样做之后,他们就可以编译和执行这样的程序。

初始化示例的适用部分是8.5.4 [dcl.init.list]。特别地,

否则,如果初始化程序列表有一个类型为E的元素,并且T不是引用类型,或者其引用类型与E相关,则从该元素初始化对象或引用;如果需要缩小转换(参见下文)才能将元素转换为T,则程序不正确。

附例

代码语言:javascript
复制
int x1 {2}; // OK
int x2 {2.0}; // error: narrowing

由于诊断的确切性质是指定的实现,因此所观察到的两组行为都符合标准。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28466069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档