#include <iostream>
#include <string>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <vector>
class Base{
public:
virtual ~Base() {}
};
class Derived: public Base { };
int main(){
int arr[10];
Derived d;
Base *p = &d;
std::map<std::type_index, std::string> proper_name = {
{typeid(int), "int"}, {typeid(double), "double"}, {typeid(float), "float"}, {typeid(char), "char"},
{typeid(Base), "Base"}, {typeid(Derived), "Derived"}, {typeid(std::string), "String"},
{typeid(int[10]), "Ten int Array"}, {typeid(p), "Base Pointer"}};
}
我试图理解此列表初始化中发生的隐式转换。来自 13.3.1.7
N3337的:
When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases:
Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument.
If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.
8.5.4
:
A constructor is an initializer-list constructor if its first parameter is of type
std::initializer_list<E>
or reference to possibly cv-qualifiedstd::initializer_list<E>
for some typeE
, and either there are no other parameters or else all other parameters have default arguments
所以the following std::map
的构造函数列表表示
map (initializer_list<value_type> il,
const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type())
;
是候选函数,value_type
在本例中是 pair<const type_index, std::string>
。最后来自13.3.3.1.5
:
If the parameter type is
std::initializer_list<X>
or “array ofX
”135 and all the elements of the initializer list can be implicitly converted toX
, the implicit conversion sequence is the worst conversion necessary to convert an element of the list toX
.
因此,只要花括号列表的元素隐式转换为 pair<const type_index, std::string>
,这就是一个有效的转换。 。但这些元素本身也是花括号列表。 Pair
不采用初始化列表构造函数,from here看来来自大括号初始化列表的复制初始化使用 13.3.1.7
的第二部分来构造对象。所以如下:
pair<const type_index, std::string> p = {typeid(int), "int"}
变成:
pair<const type_index, std::string> p(typeid(int), "int")
但这是否被视为隐式转换?如何将双参数构造函数的使用视为隐式转换?标准对此有何评论?
最佳答案
你的结论
pair<const type_index, std::string> p = {typeid(int), "int"};
变成了
pair<const type_index, std::string> p(typeid(int), "int");
不准确,因为第一个语句是复制列表初始化,而第二个语句是直接初始化。两者是相同的,除了如果选择显式构造函数,则复制列表初始化的格式不正确(并且前者不允许缩小转换)。 p>
因此,如果所讨论的 pair
构造函数定义为
template<class U1, class U2>
explicit constexpr pair(U1&& x, U2&& y);
直接初始化仍然会成功,但复制列表初始化会失败。从正下方引用您引用的[over.match.list]部分
<小时/>In copy-list-initialization, if an
explicit
constructor is chosen, the initialization is ill-formed.
除此之外,你所说的其他一切都是正确的。 pair
构造函数是隐式转换,因为构造函数不是显式
,并且根据[over.match.list]< 的第二个项目符号考虑重载决策。/em> 因为 pair
没有初始化列表构造函数。
关于c++ - 列表初始化是隐式转换吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34912221/