C++17 Neue Regeln für die automatische Deduktion von geklammerten Init-Liste

C++17 Neue Regeln für die automatische Deduktion von geklammerten Init-Liste

Die Initialisierung von Variablen in C++ kann mehrere Formen haben:

  • Standardinitialisierung:std::string s;
  • Wertinitialisierung:std::string s{};
  • direkte Initialisierung:std::string s("demo");
  • Initialisierung kopieren:std::string s ="demo";
  • Listeninitialisierung:std::string s{'d', 'e', ​​'m', 'o'};
  • Aggregatinitialisierung:char s[5] ={'d', 'e', ​​'m', 'o'};
  • Referenzinitialisierung:char&c =s[0];

C++11 hat eine verallgemeinerte Syntax für die Initialisierung mit einer geklammerten Initialisierungsliste eingeführt, die als geklammerte Initialisierungsliste bezeichnet wird. Die Initialisierung mit geklammerter Init-Liste wird als Listeninitialisierung bezeichnet. Es gibt zwei Arten der Listeninitialisierung, die jeweils mehrere Formen haben (überprüfen Sie die obigen Links), aber vereinfacht können wir haben:

  • direkte Listeninitialisierung:T-Objekt {arg1, arg2, ...};
  • Listeninitialisierung kopieren:T Objekt ={arg1, arg2, ...};

Vor C++17 war der Typ für alle folgenden Objekte (a , b , c und d ) wird zu std::initializer_list abgeleitet . Es gibt keinen Unterschied zwischen der direkten Listeninitialisierung und der Kopierlisteninitialisierung auf das Ergebnis der Typableitung.

auto a = {42};   // std::initializer_list<int>
auto b {42};     // std::initializer_list<int>
auto c = {1, 2}; // std::initializer_list<int>
auto d {1, 2};   // std::initializer_list<int>

Dies änderte sich jedoch in C++17, das die folgenden Regeln einführte:

  • Für die Initialisierung der Kopierliste wird die automatische Ableitung eine std::initializer_list ableiten ob alle Elemente in der Liste denselben Typ haben oder falsch formatiert sind.
  • Für die direkte Listeninitialisierung wird beim automatischen Abzug ein T abgeleitet wenn die Liste ein einzelnes Element hat, oder falsch formatiert sein, wenn es mehr als ein Element gibt.

Als Ergebnis ändert sich das obige Beispiel so, dass a und c sind immer noch std::initializer_list aber b wird als int abgeleitet und d ist falsch formatiert, weil es mehr als einen Wert in der Klammer-Init-Liste gibt.

auto a = {42};   // std::initializer_list<int>
auto b {42};     // int
auto c = {1, 2}; // std::initializer_list<int>
auto d {1, 2};   // error, too many 

Weitere Informationen zu diesen Änderungen finden Sie unter N3922:Neue Regeln für die automatische Deduktion von geklammerten Initialisierungslisten.