首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在使用std::initializer_list时防止缩小转换

在使用std::initializer_list时防止缩小转换
EN

Stack Overflow用户
提问于 2013-06-05 20:04:00
回答 4查看 5.1K关注 0票数 20
代码语言:javascript
复制
#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]
}

有没有其他方法可以从重载列表中删除std::initializer_list (即,使非列表ctor更有利),而不是使用()-initialization,或者至少禁止发生缩小转换(除了将警告变成错误之外)?

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-06-05 20:18:48

实际上,在大括号列表初始化器中包含缩小转换的程序是格式错误的。我不确定为什么编译器只是给你一个警告,但它肯定会在这里发出一个错误(FWIW,Clang does that)。

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

代码语言:javascript
复制
int x { 1.0f }; // ERROR! Narrowing conversion required

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

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

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

-否则,如果初始值设定项列表没有元素...

-否则,如果Tstd::initializer_list<E>的特殊化,...

-否则,如果T是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载解析(13.3,13.3.1.7)选择最佳构造函数。如果需要进行缩小转换(见下文)来转换任何参数,则程序是格式错误的。..。

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

票数 19
EN

Stack Overflow用户

发布于 2013-06-05 20:21:15

这看起来像是一个编译器错误。你应该得到一个错误而不是警告。大括号初始化不应该隐式地缩小范围。

来自标准(§8.5.4)

结构B{ B(std::initializer_list);};B b1 { 1,2 };//创建initializer_list并调用构造函数B b2 { 1,2.0 };//错误:缩小

票数 3
EN

Stack Overflow用户

发布于 2013-06-06 00:59:52

您可以使用std::enable_if实现您想要的功能。

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

struct X {
    template<typename T, typename = typename std::enable_if<std::is_same<T,int>::value>::type>
    X(std::initializer_list<T>) { std::cout << "list" << std::endl; }
    X(float) { std::cout << "float" << std::endl; }
};

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

适用于g++4.8和Clang3.2

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

https://stackoverflow.com/questions/16939471

复制
相关文章

相似问题

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