为什么 {1, 2} 没有类型,但 decltype(a) 格式正确

Why does {1, 2} has no a type, but decltype(a) is well-formed?

本文关键字:decltype 格式 类型 为什么      更新时间:2023-10-16

标准说braced-init-list没有类型。所以我预计像auto a = {1, 2};这样的东西是格式不正确的。但这根本不是真的。

#include <iostream>
#include <initializer_list>
using namespace std;
auto a = {1, 2};
std::initializer_list<int> init_list = {1, 3, 6, 7};
decltype(a) b = init_list;
int main(){ }

演示

此外,decltype(a) std::initializer_list<int>.对我来说,它与初始化程序列表没有类型相矛盾。怎么了?

decltype({1, 2})是非法的,但是,已经推断出a的类型。从最接近 C++11 标准的草案 N3337:

§7.1.6.4/6

一旦根据以下条件确定了声明符 ID 的类型 8.3,使用声明符 ID 的声明变量的类型由其初始值设定项的类型确定,使用 模板参数推导。让T成为曾经的类型 为变量标识符 d 确定。通过以下方式从T获取P 用新发明的类型替换auto的出现 模板参数U或者,如果初始值设定项是大括号初始化列表 (8.5.4(,std::initializer_list<U> .推导的类型 变量d A然后是使用 从函数调用 (14.8.2.1( 中推导模板参数,其中P 是函数模板参数类型,d的初始值设定项是 相应的参数。如果扣除失败,则申报为 格式不正确。[ 示例:

auto x1 = { 1, 2 };   // decltype(x1) is std::initializer_list<int>
auto x2 = { 1, 2.0 }; // error: cannot deduce element type

结束示例 ]

在你的问题的上下文中,大括号的初始化列表被推导出为一个std::initializer_list<int>,随后,decltype(a)产生相同的类型。

来自 c++ 标准(7.1.6.4 自动说明符(

7....如果占位符是自动类型说明符,则使用模板参数推导规则确定推导的类型。如果 扣除额适用于 Return 语句,初始值设定项为 大括号初始化列表 (8.5.4(,程序格式不正确。否则,获取 从 T 开始的 P,方法是将 auto 的出现替换为新的 发明了类型模板参数 U,或者,如果初始值设定项是 大括号初始化列表,带有 std::initializer_list。推导出 U 的值 使用从函数调用中推导模板参数的规则 (14.8.2.1(,其中 P 是函数模板参数类型,而 初始值设定项是相应的参数。如果扣除失败, 声明格式不正确。否则,推导的类型为 变量或返回类型是通过将推导的 U 代入 P. [

Example:
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>