tem*_*def 9 c++ initializer-list language-lawyer c++11 list-initialization
在C++ 11中,初始化a似乎是合法的std::map<std::string, int>,如下所示:
std::map<std::string, int> myMap = {
{ "One", 1 },
{ "Two", 2 },
{ "Three", 3 }
};
Run Code Online (Sandbox Code Playgroud)
直观地看,这是有道理的-在括号内的初始化是对串的名单,并std::map<std::string, int>::value_type为std::pair<std::string, int>(可能有一些const资质.
但是,我不确定我是否理解这里的打字工作方式.如果我们在这里消除变量声明并且只是使用大括号括起初始化器,编译器就不会知道它正在查看a,std::initializer_list<std::pair<std::string, int>>因为它不知道被支撑的对代表std::pairs.因此,似乎编译器以某种方式推迟将类型赋值给括号封闭的初始化器,直到它从std::map构造函数中获得足够的类型信息来实现嵌套大括号用于对.我不记得在C++ 03中发生过这样的事情; 据我所知,表达式的类型从不依赖于它的上下文.
哪些语言规则允许此代码正确编译,以及编译器确定用于初始化列表的类型?我希望能够获得有关C++ 11规范的具体参考的答案,因为它的确很有意义!
谢谢!
在表达中
std::map<std::string, int> myMap = {
{ "One", 1 },
{ "Two", 2 },
{ "Three", 3 }
};
Run Code Online (Sandbox Code Playgroud)
在右侧,你有一个braced-init-list,其中每个元素也是一个braced-init-list.首先发生的std::map是考虑初始化列表构造函数.
map(initializer_list<value_type>,
const Compare& = Compare(),
const Allocator& = Allocator());
Run Code Online (Sandbox Code Playgroud)
map<K, V>::value_typepair<const K, V>在这种情况下,是一个typedef pair<const string, int>.内部braced-init-lists可以成功转换为,map::value_type因为它std::pair有一个构造函数,它接受对它的两个组成类型的引用,并且std::string有一个带有a的隐式转换构造函数char const *.
因此初始化列表构造函数std::map是可行的,并且构造可以从嵌套的braced-init-lists发生.
相关标准见§13.3.1.7/ 1 [over.match.list]
当非聚合类类型的对象
T被列表初始化(8.5.4)时,重载决策分两个阶段选择构造函数:
- 最初,候选函数是类的初始化列表构造函数(8.5.4)T和参数list包含初始化列表作为单个参数.
- 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类的所有构造函数,T参数列表由初始化列表的元素组成.
第一个项目符号是导致为外部braced-init-list选择initializer_list构造函数的原因map,而第二个项目符号导致pair为内部braced-init-lists 选择正确的构造函数.
| 归档时间: |
|
| 查看次数: |
362 次 |
| 最近记录: |