c++ - 什么语言规则允许 C++11 推断这是一个 initializer_list 对?

标签 c++ c++11 language-lawyer initializer-list list-initialization

在 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_typestd::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_typepair<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 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.

第一个项目符号是导致 initializer_list 的原因map 的构造函数被选择用于外部支撑初始化列表,而第二个项目符号导致选择正确的 pair内部花括号初始化列表的构造函数。

关于c++ - 什么语言规则允许 C++11 推断这是一个 initializer_list 对?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24718555/

相关文章:

c++ - 递归可变函数模板

c++ - 基于范围的多维数组自动循环作为函数参数

c++ - atomic() 中的++、add 操作和 fetch_add() 有什么区别

c++ - clang 5:std::optional 实例化参数类型的 std::is_constructible 特征

C++ 做它想做的事 | Char[] cout 和 inverted char[]

c++ - 如何使用 Qt 的 native OpenGL 获取我的总 GPU 内存?

c++ - 错误 : expression cannot be used as an function

c++ - 初始化数组,放置新的,读取变量,定义行为?

c++ - 将联盟重新解释为其他联盟

c# - C# 真的比说 C++ 慢吗?