return和auto deduce std :: initializer_list

a.l*_*ram 9 c++ c++11

在下面的:

auto x = {0}; // auto deduction of std::initializer_list<int>
auto y = []() -> std::initializer_list<int> { return {0}; }(); //explicit
auto z = []() { return {0}; }(); // won't compile
Run Code Online (Sandbox Code Playgroud)

为什么不能返回并自动推断出std :: initializer_list的类型?

And*_*owl 8

好吧,因为标准这样说,并且因为braced-init-list不是表达式.根据C++ 11标准的5.1.2/4段:

[...]如果lambda表达式不包含trailing-return-type,则就好像trailing-return-type表示以下类型:

- 如果复合语句是形式

{ attribute-specifier-seq(opt) return 表达式 ; }

lvalue-to-rvalue转换(4.1),数组到指针转换(4.2)和函数到指针转换(4.3)之后返回表达式的类型 ;

- 否则,void.

上面清楚地表明返回类型将被推导为其他任何东西,void当且仅当return语句后跟一个表达式时,并且braced-init-list本身不是表达式 - 它没有类型,它没有产生价值.它只是一种可以在初始化环境中使用的语言结构.

以上段落也提供了一个例子:

[ 例如:

auto x1 = [](int i){ return i; }; // OK: return type is int
auto x2 = []{ return { 1, 2 }; }; // error: the return type is void (a
                                  // braced-init-list is not an expression)
Run Code Online (Sandbox Code Playgroud)

- 结束例子 ]

最后,如果问题是:

" 为什么引入了一个特殊的规则来推断auto从braced-init-list初始化的变量的类型,而当引入一个braced-init-list时,没有引入类似的规则来推断lambda的返回类型return "

那么问题就不具有建设性.另请注意,模板的类型推导不适用于braced-init-lists:

template<typename T>
void foo(T);

foo({1, 2}); // ERROR! T is NOT deduced to be std::initializer_list<int>
Run Code Online (Sandbox Code Playgroud)