在 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::pair
秒。因此,编译器似乎以某种方式推迟了将类型分配给大括号括起来的初始化程序的行为,直到它从 std::map
中获得足够的类型信息。构造函数来实现嵌套大括号是成对的。我不记得在 C++03 中发生过这样的事情;据我所知,表达式的类型从不依赖于它的上下文。
什么语言规则允许此代码正确编译并由编译器确定用于初始化列表的类型?我希望通过对 C++11 规范的具体引用来获得答案,因为这真的很有趣!
谢谢!
最佳答案
在表达式中
std::map<std::string, int> myMap = {
{ "One", 1 },
{ "Two", 2 },
{ "Three", 3 }
};
在右侧有一个braced-init-list,其中每个元素也是一个braced-init-list。发生的第一件事是 std::map
的初始化列表构造函数被认为。
map(initializer_list<value_type>,
const Compare& = Compare(),
const Allocator& = Allocator());
map<K, V>::value_type
是 pair<const K, V>
的类型定义, 在这种情况下 pair<const string, int>
.内部花括号初始化列表可以成功转换为 map::value_type
因为std::pair
有一个构造函数引用它的两个组成类型,并且 std::string
有一个接受 char const *
的隐式转换构造函数.
因此 std::map
的初始化列表构造函数 |是可行的,并且构造可以从嵌套的 braced-init-lists 发生。
相关的标准语出现在§13.3.1.7/1 [over.match.list]
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 classT
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 classT
and the argument list consists of the elements of the initializer list.
第一个项目符号是导致 initializer_list
的原因map
的构造函数被选择用于外部支撑初始化列表,而第二个项目符号导致选择正确的 pair
内部花括号初始化列表的构造函数。
关于c++ - 什么语言规则允许 C++11 推断这是一个 initializer_list 对?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24718555/