C++17 中有條修改
n3922 細想之後挺有意思的。
C++11 中規定,下面的程式碼會推導出一個 std::initializer_list<int>:
auto i{ 10 }; // i is a std::initializer_list<int>
當初在 C++11 看到時,覺得的確不太直覺,但當時記性還行,索性就記得說:新語言特性(auto)喜歡跟新語言特性(initializer_list)一起。後來在 C++17 中修改了,
For direct list-initialization:
1. For a braced-init-list with only a single element, auto deduction will deduce from that entry;
2. For a braced-init-list with more than one element, auto deduction will be ill-formed.
也就是說,C++17 後變成了: auto + direct initialization + braced-init-list 只能初始化單一一個變數。
auto i{ 10 }; // legal and i is a std::initialize_list<int>
auto i{ 10, 11 }; // illegal
岔題一下:auto + direct initialization + braced-init-list 沒辦法用在 C-style array 上,所以下面在 C++11 和 C++17 都是非法的。
auto array[]{ 10, 11 }; // illegal
auto array2[ 2 ]{ 10, 11 }; // illegal
但如果今天場景變成 auto + copy initialization + braced-init-list 那就總是會定義出一個 std::initialize_list<int> 變數了。
auto i = { 10 }; // legal and i is a std::initializer_list<int>
auto array = { 10, 11 }; // legal and array is a std::initializer_list<int>
哎,那這次要怎麼記得這件規則呢?顧名思義:等號右邊是 braced-init-list ,所以它原本就是 std::initialize_list<int> ,那既然是 copy initialization 。那就連型別也一起 copy 吧~真是太哲學了!
好吧,因為是哲學,所以有點不太科學:return value 可以視為一種 copy initialization ,但這情況下,是不能使用 auto 推導出 std::initialize_list<int> 的,因為 braced-init-list 不是一個 expression ,並不會產生一個 value [
1] 。因此 return type 需要一個明確的型別來搭配,並用來呼叫 return type 的 constructor 的 ...
auto f()
{
return {1,2}; // ill-formed, {1,2} is not an expression
}
...