#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"}};
}
我试图理解在这个列表初始化中发生的隐式转换。从N3337的
13.3.1.7
中得知:当非聚合类类型T的对象进行列表初始化(8.5.4)时,重载决议会分两个阶段选择构造函数: 1. 最初,候选函数是类T的初始化器列表构造函数(8.5.4),参数列表由初始化器列表作为单个参数组成。 2. 如果没有可行的初始化器列表构造函数,则再次执行重载决议,其中候选函数是类T的所有构造函数,参数列表由初始化器列表的元素组成。
8.5.4
:
std::initializer_list<E>
或者是可能带有cv限定符的std::initializer_list<E>
的引用,其中E
是某种类型,且除此之外没有其他参数或者所有其他参数都有默认值,则该构造函数是初始化列表构造函数。因此,
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
:如果参数类型为
std::initializer_list<X>
或“X
数组”135,并且初始化列表的所有元素都可以隐式转换为X
,则隐式转换序列是将列表中的元素转换为X
所需的最差转换。只要花括号列表的元素可以隐式转换为
pair<const type_index, std::string>
,就是有效的转换。但是这些元素本身也是花括号列表。 Pair
不采用初始化器列表构造函数,从这里链接看起来从花括号初始化列表进行复制初始化使用13.3.1.7
的第二部分来构造对象。因此以下内容:pair<const type_index, std::string> p = {typeid(int), "int"}
变成:
pair<const type_index, std::string> p(typeid(int), "int")
但这是否被视为隐式转换?如何将使用两个参数的构造函数视为隐式转换?标准对此有何评论?