Red*_*III 20 c++ initializer-list c++11
#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]
}
Run Code Online (Sandbox Code Playgroud)
有没有其他方法可以std::initializer_list从过载列表中删除(即,使非列表ctors更有利),而不是使用()初始化,或者至少禁止缩小转换(除了将警告变为错误)?
我使用的是使用GCC 4.8的http://coliru.stacked-crooked.com/编译器.
And*_*owl 19
实际上,在括号列表初始化器中包含缩小转换的程序是不正确的.我不确定为什么编译器只是给你一个警告,但它肯定应该在这里发出一个错误(FWIW,Clang这样做).
另请注意,这也是一种缩小(因而非法)的转换:
int x { 1.0f }; // ERROR! Narrowing conversion required
Run Code Online (Sandbox Code Playgroud)
根据C++ 11标准的第8.5.4/3段:
列表初始化对象或类型T的引用定义如下:
- 如果
T是聚合,则执行聚合初始化(8.5.1).[...]- 否则,如果初始化列表没有元素[...]
- 否则,如果
T是专业化std::initializer_list<E>,[...]- 否则,如果
T是类类型,则考虑构造函数.枚举适用的构造函数,并通过重载决策(13.3,13.3.1.7)选择最佳构造函数.如果转换任何参数需要缩小转换(见下文),则程序格式错误.[...]
更确切地说,标准只说在这种情况下需要"诊断",并且警告是诊断,因此编译器的行为是符合的 - 但我相信发出错误将是更好的行为.