1

最近我意識到,在C++ 11我們可以稱之爲一個委託初始化列表構造像用括號調用構造函數,而不是括號

Foo() : Foo{42} // delegate to Foo(initializer_list<>) 

這是語法正確嗎?它似乎是,雖然我本來希望在調用函數時總是使用括號,如Foo({42})。在這兩個鐺++和g ++

#include <iostream> 
#include <initializer_list> 

struct Foo 
{ 
    Foo() : Foo{42} // I would have expected invalid syntax, use Foo({42}) 
    { 
     std::cout << "Foo()... delegating constructor\n"; 
    } 
    Foo(std::initializer_list<int>) 
    { 
     std::cout << "Foo(initializer_list)\n"; 
    } 
}; 

int main() 
{ 
    Foo foo; 
} 

下面compiles fine的示例代碼我深知統一初始化的,就像使用{ }聲明對象,但不知道我們還可以調用構造函數。我們不能通話功能,雖然,以下doesn't compile

#include <initializer_list> 

void f(std::initializer_list<int>){} 

int main() 
{ 
    f{5}; // compile time error, must use f({5}) 
} 

因此,要總結,我的問題是:被委託的構造函數,允許調用只用花括號中的初始列表構造函數時有特殊規則,像Foo{something}

+0

你問最有趣的問題 – AndyG

回答

5

是的,一個MEM-初始化Foo{42}可以包含一個括號的表達式列表支撐-INIT列表。無論mem-initializer-id表示構造函數的類,基類還是成員:無論是構造函數委託還是構造函數都不成立時,都是如此。請參見[class.base.init]中的語法。

此外,該標準規定([class.base.init]在C++ 14/7),其由所述表達式列表支撐-INIT列表初始化根據通常的規則發生初始化。因此,如果初始化程序是一個支持初始化列表那麼std::initializer_list構造函數將在重載分辨率中受到青睞。

2

我認爲規則是很清楚,你將被允許委託給一個初始化列表構造(重點煤礦):

如果該類自己的名字出現在類或標識符 成員初始值設定項列表,則該列表必須只包含該成員初始值設定項的一個成員 ;這樣的構造是被稱爲委託 構造,並且由 初始化列表的唯一成員所選擇的構造是在目標的構造在這種情況下,目標 構造由重載解析選擇並執行第一, 則控制返回到委託構造函數,其執行體 。

因此,通過重載解析,您可以調用您的初始化程序列表構造函數,就像在「普通」代碼中調用它一樣,因爲。

但是,我不知道任何應該允許調用一個函數來接受一個初始化列表,就像你可以調用一個構造函數一樣。

編輯:More約構造規則(重點再次礦):

任何構造函數定義的主體,複合語句的 開括號之前,可能包括成員 初始化列表,其語法是冒號:,隨後 逗號分隔的一個或多個成員初始化列表,每個的 ,其具有下面的語法
     類或標識符(表達式列表(可選))(1)
      類或標識符支架-INIT列表(2)(由於C++ 11)
     參數-pack ...(3)(因爲C++ 11)

1)初始化使用 直接初始化,或者,如果表達式列表是空的, 值初始化由類或標識符命名基部或構件
2)初始化由 命名的基類或成員class-or-使用列表初始化(成爲 值初始化,如果該列表爲空並初始化一個聚合時聚合初始化 )
3)初始化使用 包膨脹

所以根據#多個鹼基標識符2,它看起來是合法的。

+0

我明白這一點,我知道我可以委託給一個init-list,但不知道我也可以稱它爲'Foo {...}'而不一定是'Foo ({...})'。 – vsoftco