C++ 为什么这个初始值设定项\列表构造函数是一个可行的重载?
而g++48-std=c++11则选择了产生警告来诊断不正确的狭窄C++ 为什么这个初始值设定项\列表构造函数是一个可行的重载?,c++,c++11,language-lawyer,overload-resolution,list-initialization,C++,C++11,Language Lawyer,Overload Resolution,List Initialization,而g++48-std=c++11则选择了产生警告来诊断不正确的狭窄 init.cpp:15:14: error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing] A a1 = {1, 1.0}; ^~~ init.cpp:15:14: note: insert an explicit cast to silence this issue A a1
init.cpp:15:14: error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
A a1 = {1, 1.0};
^~~
init.cpp:15:14: note: insert an explicit cast to silence this issue
A a1 = {1, 1.0};
^~~
static_cast<int>( )
并产生结果
init.cpp: In function ‘int main()’:
init.cpp:15:17: warning: narrowing conversion of ‘1.0e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
A a1 = {1, 1.0};
^
init.cpp:15:17: warning: narrowing conversion of ‘1.0e+0’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
{1,1.0}不能隐式转换为std::initializer_list
使用13.3.2中的引文,当对a1={1,1.0};执行重载解析时,难道不应该暗示A::Astd::initializer_list不是一个可行的函数吗;?如果找不到可行的初始值设定项列表构造函数,该语句是否应该选择一个::Aint,double?我相信您分析中的问题是,该语句
std::initializer_list<int> e = {1, 1.0};
确实格式良好-显然存在从double到int的隐式转换。[over.ics.list]/4还描述了它:
否则,如果参数类型为std::initializer_list and all
初始值设定项列表的元素可以隐式转换为
十、 隐式转换序列是最差的转换
需要将列表中的某个元素转换为X,或者
初始值设定项列表没有元素,身份转换
初始值设定项列表中的每个元素都可以隐式转换为int,因此构造函数是可行的,并且是可选择的。但是,只有选择了它,整个过程才会出现错误,[dcl.init.list]/3.6:
列举了适用的构造函数,并选择了最佳构造函数
通过过载决议13.3、13.3.1.7。如果是变窄
转换任何参数都需要转换,请参见下文,
这个程序格式不好
如您所见,要调用的构造函数是在执行缩小检查之前确定的。换句话说,初始值设定项列表构造函数的可行性并不取决于任何参数的缩小。
因此,代码的格式应该是错误的
获得所需行为的一种方法是在SFINAE中使用构造函数模板
int t = 1.0;
.8.5.1如何申请int t=1.0;?这不是聚合初始化,是吗?你在帖子中提到,使用初始化列表的构造函数是非常受欢迎的。因此编译器选择初始值设定项列表构造函数,然后尝试转换,因为它缩小了编译的范围,所以编译失败。@Columbo抱歉,我没有理解你的意思。另外,对于8.5.1,我没有粘贴整个标准引用,但既然您提到了聚合初始化,我想这已经足够清楚了。@NathanOliver是的,但Scott Meyers更倾向于用简单的英语编写标准。“我在问它是如何从标准语中得出的。”普拉丹我发布了一个答案,以使我的观点更加清晰。啊,好吧,这似乎可以解释它。检查这些部分以确保我理解。你认为是什么标准以这种看似复杂的方式规定了它?为什么不简单地确保它不是一个可行的过载?这是为了避免使聚合初始化复杂化吗?如果他们要区分={1,1.0}和={1,1.0},我不知道。似乎我们缺少了一些角点情况,或者节有缺陷。我认为如果所使用的构造函数依赖于从整数到整数类型转换的参数值,这会很奇怪,例如,源是一个常量表达式。
std::initializer_list<int> e = {1, 1.0};
int t = 1.0;
template <typename T, typename=std::enable_if_t<std::is_same<int, T>{}>>
A(std::initializer_list<T>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }