MWi*_*Wid 5 c++ types initializer-list auto c++11
在SO上已经有类似的问题,但我想强调braced-init-lists的另一个方面.考虑以下:
auto x = {1}; //(1)
Run Code Online (Sandbox Code Playgroud)
除非<initializer_list>包含标题,否则这是不正确的(8.5.4/2).但为什么?标准说,模板std::initializer_list不是预定义的.这是否意味着,声明(1)引入了一种新类型?在所有其他情况下,auto可以使用的地方如
auto y = expr;
Run Code Online (Sandbox Code Playgroud)
where expr是表达式,auto deduces类型已经存在.另一方面,从逻辑的角度来看,编译器必须为构造分配一个implicite类型{1},std::initializer_list然后是另一个名称.但是在声明(1)中我们不想命名这种类型.那么为什么必须包括这个标题.有类似的情况nullptr.它的类型隐含存在,但要明确指出它必须包括<cstddef>.
那不一样.规则std::nullptr_t和std::initializer_list实际上是不同的.
std::nullptr_t只是内置类型的typedef.它的定义是
namespace std {
using nullptr_t = decltype(nullptr);
}
Run Code Online (Sandbox Code Playgroud)
无论您是否包含标题,都存在该类型.
std::initializer_list是一个类模板,而不是预定义的类型.除非您包含定义它的标头,否则它确实不存在.特别是,初始化列表{ 1 }没有类型std::initializer_list<int>; 它根本没有类型,因为它不是表达式.(初始化列表是特殊的语法结构,不能出现在表达式的任何地方.)
std::initializer_list只是有点特别.例如,如何std::initializer_list从初始化列表语法初始化a (分配数组并让对象引用它)有一些特殊规则.但是,这需要std::initializer_list首先定义.
第二个特例是auto类型扣除.这里也有一个特殊的规则.但同样,这并不意味着编译器会自动定义类型; 它只是意味着它会识别它.