2011-08-18 127 views
17

std::initializer_list由編譯器從大括號括起來的init列表構造而成,並且此列表的大小必須是編譯時間常量。爲什麼大小不是std :: initializer_list的模板參數?

那麼爲什麼委員會決定從模板參數中省略大小呢?這可能會阻止某些優化並使某些事情不可行(從std::initializer_list初始化std::array)。

+4

一個非常類似的問題是: 「爲什麼'的std :: initializer_list :: size'不'constexpr'(了)?」這是一年前在clC++ m上提出的。 – MSalters

+1

Re MSalters'2011評論,請注意,即使C++ 11沒有,C++ 14 *也會使std :: initializer_list :: size成爲'constexpr'函數。 http://en.cppreference.com/w/cpp/utility/initializer_list/size – Quuxplusone

回答

7

現有系統的一個優點是可以導出從DLL中取出initializer_list的函數。如果它是根據尺寸模板化的,則必須將其作爲源代碼進行發貨。

+4

沿着同樣的路線:它可能會導致一些不平凡的膨脹。 – MSalters

13

如果initializer_list被定義爲std::initializer_list<type, size>,然後任何函數,它的initializer_list<type>,其中type是一些具體的類型,現在就必須根據該列表的大小的模板功能。或者他們將不得不要求用戶通過的特定類型的initializer_list並且尺寸爲

這兩個都是非常不可接受的。並非所有人都將他們的代碼編寫爲模板。

您可以從braced-init-list({}中間的東西)初始化一個std::array。但這與std::intiializer_list不一樣。 array類是一個聚合類型。它是一個包含單個元素的結構,它是一個公共數組。因此,在一個符合C++ 11個實施方式中,這應該編譯:

std::array<int, 3> myArray = {1, 3, 5}; 

然而,{1, 3, 5}不是std::initializer_list對象;它只是一個braced-init-list,可以用來初始化適當的類型。

您不能std::initializer_list對象傳遞給aggegate的構造函數(因爲聚集有沒有構造函數),但你可以使用一個支撐,初始化列表來調用集合初始化,初始化std::array,就像你對任何結構包含一個數組。

std::initializer_list與加載初始化列表之間的區別有點像int和字面0之間的區別。將(int)對象隱式轉換爲指針類型並不是(通常)合法的,但將整數文字0隱式轉換爲指針類型是合法的。方式支撐-INIT-名單的工作是這樣的:

int i = 0; //Legal 
void *j = 0; //Legal 
void *k = i; //Not legal 

std::array<int, 3> myArray = {1, 3, 5};    //Legal 
std::initializer_list<int> myInitList = {1, 3, 5}; //Legal 
std::array<int, 3> myArray = myInitList;   //Not legal 
+0

你確定要從'std :: initializer_list'初始化'std :: array'嗎? '數組 x = {1,2,3}'不適用於gcc 4.6,我不能推斷這應該從n3242起作用。 – pmr

+0

@pmr:std :: array被定義(在N3291中)爲一個結構體,它遵循C++ 0x規則的聚合類型。因此,它應該通過聚合初始化進行初始化。所以你初始化它,就好像它是一個持有3個元素的數組的結構。我會更新我的帖子來解釋這一點。 –

+1

@Nicol:這只是聚合初始化 - 'initializer_list'是完全正交的。 – ildjarn

相關問題