2011-08-18 14 views
17

std::initializer_list jest skonstruowany przez kompilator z listy kontrolnej dołączanej przez nawiasy klamrowe, a rozmiar tej listy musi być stałą czasową kompilacji.Dlaczego rozmiar nie jest szablonem argumentu std :: initializer_list?

Dlaczego więc komisja postanowiła pominąć rozmiar z argumentów szablonu? To prawdopodobnie uniemożliwia pewne optymalizacje i uniemożliwia pewne rzeczy (inicjowanie std::array z std::initializer_list).

+4

Bardzo podobne pytanie "dlaczego jest' std :: initializer_list :: size' nie 'constexpr' (już)?" który został zapytany na clC++ m rok temu. – MSalters

+1

Komentarz Re MSalters 2011, zauważ, że C++ 14 * robi * sprawia, że ​​'std :: initializer_list :: size' jest funkcją' constexpr', mimo że C++ 11 nie. http://pl.cppreference.com/w/cpp/utility/initializer_list/size – Quuxplusone

Odpowiedz

7

Jedną z zalet istniejącego systemu jest możliwość eksportu funkcji, które pobierają initializer_list z biblioteki DLL. Gdyby szablony były szablonowe, musiałyby zostać wysłane jako źródło.

+4

W tym samym wierszu: może powodować pewne niebanalne wzdęcia. – MSalters

13

Jeśli initializer_list zdefiniowano jako std::initializer_list<type, size>, następnie dowolny funkcja, która bierze initializer_list<type>, gdzie type jest jakiś konkretny typ, będzie teraz musiał być funkcją szablon na podstawie tego wykazu jest wielkości. Mogą też wymagać od użytkowników przekazywania initializer_list określonego typu i rozmiaru.

Oba są dość niedopuszczalne. Nie wszyscy zapisują cały swój kod jako szablony.

Można zainicjować std::array z listy z zaprawionymi początkami ({} z materiałem na środku). Ale to nie to samo co std::intiializer_list. Klasa array jest typem zagregowanym. Jest to struktura, która zawiera pojedynczy element, który jest tablicą publiczną. Dlatego na zgodnej C++ 11 wdrożeń, należy skompilować:

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

Jednak {1, 3, 5} nie jest std::initializer_list przedmiot; jest to po prostu lista ze wzmocnionymi początkami, która może być użyta do zainicjowania odpowiednich typów.

Nie można przekazać std::initializer_list obiektu do konstruktora w aggegate (bo agregaty nie mają konstruktorów), ale można użyć usztywnione-init-listy powołać łączną inicjalizacji zainicjować std::array, podobnie jak w przypadku każdej struktury zawierające tablicę.

Różnica między std::initializer_list a listą z ustalonymi początkami przypomina nieco różnicę między int a literalnym 0. Nie jest (zwykle) legalne przekonwertowanie obiektu int na typ wskaźnika, ale legalne jest niejawne przekonwertowanie liczby całkowitej 0 na typ wskaźnika. Sposób usztywnione-init-list praca jest tak:

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

Czy jesteś pewien co do inicjowania 'std :: array' z' std :: initializer_list'? 'tablica x = {1,2,3}' nie działa na gcc 4.6 i nie mogę wywnioskować, że to powinno działać z n3242. – pmr

+0

@pmr: std :: array jest zdefiniowana (w N3291) jako struct i jest zgodna z regułami C++ 0x dla typu agregującego. Dlatego należy go zainicjować poprzez inicjalizację agregacyjną. Więc zainicjuj go tak, jakby był strukturą zawierającą tablicę 3 elementów. Zaktualizuję swój post, aby to wyjaśnić. –

+1

@Nicol: To tylko inicjalizacja agregacji - 'initializer_list' jest całkowicie ortogonalna. – ildjarn

Powiązane problemy