EDYCJA: Zanim zaczniemy, to pytanie jest , a nie o poprawnym użyciu std::initializer_list
; chodzi o to, co powinno zostać przekazane, gdy pożądana jest wygodna składnia. Dziękuję za pozostanie na temat.Przepuścić listę inicjalizacyjną lub kontener, patrząc w kierunku semantyki ruchu?
C++ 11 wprowadza std::initializer_list
zdefiniować funkcje akceptujące usztywnione-startowe lista argumentów.
struct bar {
bar(char const *);
bar(int);
} dog(42);
fn foo(std::initializer_list<bar> args);
foo({ "blah", 3, dog });
Składnia jest ładne, ale pod maską jest niesmaczne powodu różnych problemów:
Nie można sensownie przeniesiony. Powyższa funkcja musi skopiować
dog
z listy; nie można tego przekonwertować na budowę ruchową ani na elekcję. Typy typu "ruch" nie mogą być w ogóle używane. (No cóż,const_cast
byłby prawdziwym obejściem. Jeśli jest jakiś artykuł na ten temat, chciałbym go zobaczyć.)Nie ma też semantyki
constexpr
. (Pojawia się to w C++ 1j. Jest to jednak drobny problem.)const
nie rozprzestrzenia się tak jak wszędzie;initializer_list
nigdy nie jestconst
, ale jej zawartość zawsze jest. (Ponieważ nie jest właścicielem jego zawartości, nie może dać prawa zapisu do kopii, ale kopiowanie jej w dowolne miejsce rzadko bywa bezpieczne.)Obiekt
initializer_list
nie jest właścicielem jego pamięci (yikes); jego związek z całkowicie oddzielną, nagą tablicą (yikes), zapewniającą przechowywanie, jest określany w sposób trudny (yikes) jako relacja odniesienia do związanej tymczasowości (poczwórne yikes).
Wierzę te rzeczy zostaną ustalone w odpowiednim czasie, ale teraz jest tam najlepszych praktyk, aby uzyskać korzyści bez twarde kodowania initializer_list
? Czy istnieje jakaś literatura lub analiza na temat bezpośredniej zależności od niej?
Oczywistym rozwiązaniem jest przekazanie według wartości standardowego pojemnika, takiego jak std::vector
. Po skopiowaniu obiektów z poziomu obiektu initializer_list
, jest on przesuwany, aby przejść przez wartość, a następnie można przenieść zawartość. Udoskonaleniem byłoby oferowanie przechowywania na stosie. Dobra biblioteka może być w stanie zaoferować większość zalet initializer_list
, array
i vector
, nawet bez korzystania z pierwszego.
Wszelkie zasoby?
[Czytałeś już to?] (Http://stackoverflow.com/questions/17623098/questions-regarding-the-design-of-stdinitializer-list/17623839#17623839) – Borgleader
@Borgleader Wydaje mi się, że to omówiłem pytanie już. Wskazujesz coś szczególnego? – Potatoswatter
Listy inicjatorów są tak zwane, ponieważ służą do * inicjowania rzeczy *. Jeśli nie inicjujesz czegoś z listą podobnych wartości, nie powinieneś przyjmować ich jako parametrów w swojej funkcji. Nie jest jasne, dlaczego 'foo' w ogóle bierze listę inicjalizującą. To nie jest pojemnik *; właśnie to jest ta odpowiedź, z którą się łączyłeś, próbując ci przypomnieć. Jeśli chcesz mieć tablicę, różni się ona od listy inicjalizatora. –