为什么必须包含<initializer_list>才能使用auto?</initializer_list>

时间:2013-06-14 09:57:01

标签: c++ c++11 types auto initializer-list

在SO上已经有类似的question,但我想强调 braced-init-lists 的另一个方面。请考虑以下事项:

auto x = {1}; //(1)

除非包含标题<initializer_list>,否则这是不正确的(8.5.4 / 2)。但为什么?标准说,模板std::initializer_list未预定义。这是否意味着,声明(1)引入了一种新类型?在所有其他情况下,可以使用auto,例如

auto y = expr;

其中expr是表达式,自动推断类型已存在。另一方面,从逻辑的角度来看,编译器必须为构造{1}分配 implicite type ,其中std::initializer_list是另一个名称。但是在声明(1)中我们不想命名这种类型。那么为什么必须包括这个标题。 nullptr也存在类似的情况。其类型隐含存在,但要明确指出它,您必须包含<cstddef>

1 个答案:

答案 0 :(得分:8)

那不一样。 std::nullptr_tstd::initializer_list的规则实际上是不同的。

std::nullptr_t只是内置类型的typedef。它的定义是

namespace std {
  using nullptr_t = decltype(nullptr);
}

无论您是否包含标题,都存在类型。

std::initializer_list是一个类模板,而不是预定义的类型。除非您包含定义它的标头,否则它确实不存在。特别是,初始化列表{ 1 }没有类型std::initializer_list<int>;它根本没有类型,因为它不是表达式。 (初始化列表是特殊的句法结构,不能出现在表达式的任何地方。)

std::initializer_list稍微有些特别。例如,有关如何从初始化列表语法初始化std::initializer_list的特殊规则(分配数组并让对象引用它)。但是,这需要首先定义std::initializer_list

第二个特例是auto类型扣除。这里也有一个特殊的规则。但同样,这并不意味着编译器会自动定义类型;它只是意味着它会识别它。