Benötigen Sie tatsächlich den zweiten Satz Zahnspangen std::arrayoder erhalten Sie nur eine Warnung? std::array<int,4> y{1,2,3,4};funktioniert bei mir.
Bames53
3
@ bames53: GCC ist falsch beim Kompilieren.
Xeo
14
@Xeo: Es ist nicht "falsch", ein schlecht geformtes Programm mit einer Warnung zu kompilieren.
Steve Jessop
3
@Steve: Stimmt das. Sagen wir nicht tragbar?
Xeo
2
@Xeo: Ja, ich verwende es -Werrorsowieso für Code, den ich geschrieben habe, also schadet es meiner Portabilität nicht. Die Laufleistung anderer kann variieren, wenn sie Leichtgewichte sind oder Header-Dateien enthalten müssen, die von Leichtgewichten geschrieben wurden :-)
Steve Jessop
Antworten:
63
std::array<T, N>ist ein Aggregat: Es gibt keine vom Benutzer deklarierten Konstruktoren, nicht einmal einen, der a nimmt std::initializer_list. Die Initialisierung mit geschweiften Klammern erfolgt mit der aggregierten Initialisierung , einer Funktion von C ++, die von C geerbt wurde.
Der "alte Stil" der Aggregatinitialisierung verwendet Folgendes =:
std::array<int, 4> y = { { 1, 2, 3, 4 } };
Bei dieser alten Art der Aggregatinitialisierung können zusätzliche Klammern entfernt werden. Dies entspricht also:
std::array<int, 4> y = { 1, 2, 3, 4 };
Diese zusätzlichen Klammern dürfen jedoch nur "in einer Deklaration der Form T x = { a };" (C ++ 11 §8.5.1 / 11) entfernt werden, dh wenn der alte Stil =verwendet wird. Diese Regel, die die Klammerelision zulässt, gilt nicht für die direkte Listeninitialisierung. Eine Fußnote lautet hier: "Klammern können bei anderen Verwendungen der Listeninitialisierung nicht entfernt werden."
Zu dieser Einschränkung gibt es einen Fehlerbericht: CWG-Fehler Nr. 1270 . Wenn die vorgeschlagene Entschließung angenommen wird, ist die Klammerentfernung für andere Formen der Listeninitialisierung zulässig, und Folgendes ist wohlgeformt:
std::array<int, 4> y{ 1, 2, 3, 4 };
(Hutspitze an Ville Voutilainen, um den Fehlerbericht zu finden.)
Es ist also ein Fehler des präsentierten Abstraktionsmodells array?
Mark Ransom
1
@Mehrdad: Es ist einheitlich. Was nicht einheitlich ist, ist die Tatsache, dass Sie zwei völlig unterschiedliche Typen initialisieren.
Nicol Bolas
5
@NicolBolas: Ich dachte, der springende Punkt der Einheitlichkeit wäre, die gleiche Initialisierungssyntax für verschiedene Typen zu verwenden? (Ja, ich verstehe, was passiert ... Ich sage nur, dass es für den Benutzer nicht "einheitlich" ist, unabhängig davon, ob es eine Erklärung dafür gibt.)
user541686
@MarkRansom: Nun, es ist eher eine Eigenart der Sprache, da es std::array<int> y = {1,2,3,4};mit einer Warnung von Clang arbeitet, die Klammern vorschlägt , anstatt eines schweren Fehlers darüber, dass bei Verwendung der direkten Listeninitialisierung keine Klammern um die Initialisierung des Unterobjekts weggelassen werden dürfen.
Xeo
1
@Xeo: Tatsächlich ist die Klammerelision bei der aggregierten Initialisierung zulässig, jedoch (anscheinend) nicht, wenn die Syntax für die direkte Listeninitialisierung verwendet wird.
James McNellis
29
Weil std::vectorbietet einen Konstruktor, der a aufnimmt std::initializer_list<T>, während er std::arraykeine Konstruktoren hat und die {1, 2, 3, 4}geschweifte Init-Liste tatsächlich nicht als std::initializer_list, sondern als aggregierte Initialisierung für das innere C-artige Array von interpretiert wird std::array(daher kommt der zweite Satz von Klammern: Eins für std::arrayeine für das innere C-Style-Member-Array).
std::array
oder erhalten Sie nur eine Warnung?std::array<int,4> y{1,2,3,4};
funktioniert bei mir.-Werror
sowieso für Code, den ich geschrieben habe, also schadet es meiner Portabilität nicht. Die Laufleistung anderer kann variieren, wenn sie Leichtgewichte sind oder Header-Dateien enthalten müssen, die von Leichtgewichten geschrieben wurden :-)Antworten:
std::array<T, N>
ist ein Aggregat: Es gibt keine vom Benutzer deklarierten Konstruktoren, nicht einmal einen, der a nimmtstd::initializer_list
. Die Initialisierung mit geschweiften Klammern erfolgt mit der aggregierten Initialisierung , einer Funktion von C ++, die von C geerbt wurde.Der "alte Stil" der Aggregatinitialisierung verwendet Folgendes
=
:std::array<int, 4> y = { { 1, 2, 3, 4 } };
Bei dieser alten Art der Aggregatinitialisierung können zusätzliche Klammern entfernt werden. Dies entspricht also:
std::array<int, 4> y = { 1, 2, 3, 4 };
Diese zusätzlichen Klammern dürfen jedoch nur "in einer Deklaration der Form
T x = { a };
" (C ++ 11 §8.5.1 / 11) entfernt werden, dh wenn der alte Stil=
verwendet wird. Diese Regel, die die Klammerelision zulässt, gilt nicht für die direkte Listeninitialisierung. Eine Fußnote lautet hier: "Klammern können bei anderen Verwendungen der Listeninitialisierung nicht entfernt werden."Zu dieser Einschränkung gibt es einen Fehlerbericht: CWG-Fehler Nr. 1270 . Wenn die vorgeschlagene Entschließung angenommen wird, ist die Klammerentfernung für andere Formen der Listeninitialisierung zulässig, und Folgendes ist wohlgeformt:
std::array<int, 4> y{ 1, 2, 3, 4 };
(Hutspitze an Ville Voutilainen, um den Fehlerbericht zu finden.)
quelle
array
?std::array<int> y = {1,2,3,4};
mit einer Warnung von Clang arbeitet, die Klammern vorschlägt , anstatt eines schweren Fehlers darüber, dass bei Verwendung der direkten Listeninitialisierung keine Klammern um die Initialisierung des Unterobjekts weggelassen werden dürfen.Weil
std::vector
bietet einen Konstruktor, der a aufnimmtstd::initializer_list<T>
, während erstd::array
keine Konstruktoren hat und die{1, 2, 3, 4}
geschweifte Init-Liste tatsächlich nicht alsstd::initializer_list
, sondern als aggregierte Initialisierung für das innere C-artige Array von interpretiert wirdstd::array
(daher kommt der zweite Satz von Klammern: Eins fürstd::array
eine für das innere C-Style-Member-Array).quelle