在使用std :: initializer_list时防止缩小转换 [英] Preventing narrowing conversion when using std::initializer_list

查看:90
本文介绍了在使用std :: initializer_list时防止缩小转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  #include< iostream> 

struct X {
X(std :: initializer_list< int> list){std :: cout< list<< std :: endl; }
X(float f){std :: cout< float<< std :: endl; }
};

int main(){
int x {1.0f};
X a(1); // float(implicit conversion)
X b {1}; // list
X c(1.0f); // float
X d {1.0f}; // list(narrowing conversion)ARG !!!

//警告:将'1.0e + 0f'的转换从'float'缩小到'int'
// inside {} [-Wnarrowing]
}

是否有其他方法可以删除 std :: initializer_list 从过载列表(即,使非列表ctors更有利),而不是使用() - 初始化,或至少禁止变窄转换发生(除了将警告变为错误)?



我使用的是 http://coliru.stacked-crooked.com/ 编译器,它使用GCC 4.8 。

解决方案

实际上,在括号列表初始化器中包含缩小转换的程序 。我不知道为什么编译器只给你一个警告,但它绝对应该在这里发布一个错误(FWIW,



另请注意,这是一个缩小(因此也是非法的)转换:

  int x {1.0f}; //错误!需要缩小转换

根据C ++ 11标准的第8.5.4 / 3节:


类型T的对象或引用的列表初始化定义如下:



- 如果 T 是聚合,则执行聚合初始化(8.5.1)。 [...]



- 如果初始值列表没有元素[...] - 否则,如果 T std :: initializer_list< E> p>

- 否则,如果 T 是类类型,则会考虑构造函数。适用的构造函数枚举为
,最好的构造函数通过重载分辨率(13.3,13.3.1.7)选择。 如果要转换任何参数时需要缩小转换(请参阅下面的
),说明程序格式错误
。 [...]


更准确地说,标准只说在这种情况下需要诊断警告是一个诊断,所以编译器的行为是符合 - 但我相信发出错误将是一个更好的行为。


#include <iostream>

struct X {
    X(std::initializer_list<int> list) { std::cout << "list" << std::endl; }
    X(float f) { std::cout << "float" << std::endl; }
};

int main() {
    int x { 1.0f };
    X a(1);     // float (implicit conversion)
    X b{1};     // list
    X c(1.0f);  // float
    X d{1.0f};  // list (narrowing conversion) ARG!!!

    // warning: narrowing conversion of '1.0e+0f' from 'float' to 'int'
    // inside { } [-Wnarrowing]
}

Is there any other way of removing std::initializer_list from an overload list (i.e., making the non-list ctors more favorable) instead of using the ()-initialization, or at least prohibiting narrowing conversion to happen (apart from turning warning into error)?

I was using http://coliru.stacked-crooked.com/ compiler which uses GCC 4.8.

解决方案

Actually, a program containing a narrowing conversion in a brace list initializer is ill-formed. I am not sure why the compiler just gives you a warning, but it definitely should issue an error here (FWIW, Clang does that).

Also notice, that this is a narrowing (and therefore illegal) conversion as well:

int x { 1.0f }; // ERROR! Narrowing conversion required

Per paragraph 8.5.4/3 of the C++11 Standard:

List-initialization of an object or reference of type T is defined as follows:

— If T is an aggregate, aggregate initialization is performed (8.5.1). [...]

— Otherwise, if the initializer list has no elements [...]

— Otherwise, if T is a specialization of std::initializer_list<E>, [...]

— Otherwise, if T is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution (13.3, 13.3.1.7). If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed. [...]

To be more precise, the Standard only says that a "diagnostic" is required in this case, and a warning is a diagnostic, so the compiler's behavior is conforming - but I believe emitting an error would be a better behavior.

这篇关于在使用std :: initializer_list时防止缩小转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆