【发布时间】:2014-07-13 00:41:31
【问题描述】:
在 C++11 中,初始化 std::map<std::string, int> 似乎是合法的,如下所示:
std::map<std::string, int> myMap = {
{ "One", 1 },
{ "Two", 2 },
{ "Three", 3 }
};
直观地说,这是有道理的 - 大括号括起来的初始值设定项是字符串对的列表,std::map<std::string, int>::value_type 是 std::pair<std::string, int>(可能带有一些 const 资格。
但是,我不确定我是否理解此处的打字工作原理。如果我们消除这里的变量声明并且只使用大括号括起来的初始化程序,编译器将不会知道它正在查看std::initializer_list<std::pair<std::string, int>>,因为它不会知道大括号对代表std::pairs。因此,似乎编译器以某种方式推迟了将类型分配给大括号封闭的初始化程序的行为,直到它从 std::map 构造函数中获得足够的类型信息以意识到嵌套的大括号是用于对的。我不记得在 C++03 中发生过这样的事情;据我所知,表达式的类型从不依赖于它的上下文。
哪些语言规则允许此代码正确编译并允许编译器确定初始化列表使用什么类型?我希望得到具体参考 C++11 规范的答案,因为这真的很有趣!
谢谢!
【问题讨论】:
-
C++03 中的大括号括起来的列表已经非常特定于初始化程序上下文。这里与使用大括号初始化的 C++03 嵌套聚合(可能是
std::pair<std::string, int> myArray[])没有显着区别,只是类型不是直接命名的,而是从可用的构造函数中推断出来的。 -
顺便说一句,隐式转换运算符(成员
operator T())是上下文确定表达式类型(并用于重载解析)的另一个地方。 -
braced-init-list不是表达式,也没有类型。没有推论,只有初始化列表构造函数(其中只有一个)之间的重载决议
标签: c++ c++11 language-lawyer initializer-list list-initialization