以下无法编译clang35 -std=c++11
:
#include <iostream>
#include <string>
#include <initializer_list>
class A
{
public:
A(int, bool) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
A(int, double) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
A(std::initializer_list<int>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
int main()
{
A a1 = {1, 1.0};
return 0;
}
有错误
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>( )
OTOH,它警告缩小并编译g++48 -std=c++11
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]
并产生结果
A::A(std::initializer_list<int>)
这两种行为都有意义吗?引用cppreference
所有将 std::initializer_list 作为唯一参数或作为第一个参数(如果其余参数具有默认值)的构造函数都将被检查,并通过重载决议与 std::initializer_list 类型的单个参数进行匹配
如果前一阶段没有产生匹配,则 T 的所有构造函数都参与重载决议,以对抗由括号初始化列表的元素组成的参数集,并限制只允许非缩小转换。如果此阶段生成显式构造函数作为复制列表初始化的最佳匹配,则编译失败(注意,在简单复制初始化中,根本不考虑显式构造函数)
由于不允许缩小转换,我希望重载解析步骤与构造函数不匹配A(std::initializer_list<int>)
,而是与构造函数匹配A(int, double)
。例如,更改A(std::initializer_list<int>)
为同时使用and和 print进行A(std::initializer_list<std::string>)
编译clang35
g++48
A::A(int, double)
正如预期的那样。