Rufen leere Klammern den Standardkonstruktor oder den Konstruktor auf, der eine std :: initializer_list verwendet?

8

Das folgende Zitat stammt von Effective Modern C ++ (Seite 55):

  

"Angenommen, Sie verwenden einen leeren Satz Klammern, um ein Objekt zu konstruieren, das den Standardkonstruktor unterstützt, und unterstützt auch die std :: initializer_list-Konstruktion. Was bedeuten Ihre leeren Klammern? usw. Die Regel ist, dass Sie die Standardkonstruktion erhalten."

Ich habe das mit std :: array versucht:

%Vor%

und erhielt die Warnung von g ++ (Version 4.8.2):

  

Warnung: fehlender Initialisierer für Member 'std :: array & lt; int, 10ul & gt; :: _ M_elems'

Dies ist die Warnung, die man erhält, wenn man versucht, ein std::array aus einem leeren std::initializer_list zu konstruieren (siehe Warum kann ich ein reguläres Array von {} initialisieren, aber nicht ein std :: -Array , um diese Warnung zu erörtern?).

Warum wird die obige Codezeile nicht als Aufruf des Standardkonstruktors interpretiert?

    
AlwaysLearning 07.07.2015, 20:11
quelle

1 Antwort

8

Das liegt daran, dass std :: array ein Aggregat ist und daher aggregation initialization wird durchgeführt, dies wird in entwurf C ++ 11 Standard Abschnitt 8.5.4 [dcl.init.list] was sagt:

  

Die Listeninitialisierung eines Objekts oder einer Referenz vom Typ T ist wie folgt definiert:

     
  • Wenn die Initialisierungsliste keine Elemente enthält und T ein Klassentyp mit einem Standardkonstruktor ist, lautet das Objekt   Wert initialisiert.

  •   
  • Andernfalls, wenn T ein Aggregat ist, wird eine Aggregatinitialisierung durchgeführt (8.5.1).

    %Vor%
  •   

und wir können sehen, ob es kein Aggregat ist, dann geht die Liste weiter und sagt:

  
  • Andernfalls, wenn T eine Spezialisierung von std :: initializer_list ist, ist ein initializer_list -Objekt   wie unten beschrieben aufgebaut und verwendet, um das Objekt gemäß den Regeln für die Initialisierung zu initialisieren   eines Objekts aus einer Klasse des gleichen Typs (8.5).
  •   
  • Andernfalls, wenn T ein Klassentyp ist, werden Konstruktoren berücksichtigt. Die anwendbaren Konstruktoren werden aufgelistet   und der beste wird durch Überladungsauflösung gewählt (13.3, 13.3.1.7). Wenn eine verkleinerte Konvertierung (siehe   unten) ist erforderlich, um eines der Argumente zu konvertieren, das Programm ist schlecht gebildet.
  •   

Wir können bestätigen, dass std::array ein Aggregat aus dem Abschnitt 23.3.2.1 [array.overview] ist:

  

Ein Array ist ein Aggregat (8.5.1), das mit dem initialisiert werden kann   Syntax

%Vor%      

wobei die Initialisiererliste eine durch Kommas getrennte Liste von bis zu N Elementen ist   deren Typen in T konvertierbar sind.

section 8.5.1 referenziert ist 8.5.1 Aggregates [dcl.init.aggr] und sagt:

  

Wenn ein Aggregat wie angegeben durch eine Initialisierungsliste initialisiert wird   In 8.5.4 werden die Elemente der Initialisierungsliste als   Initialisierer für die Mitglieder des Aggregats, in steigendem Index   oder Mitgliederbestellung [...]

und wir kommen mit dem Vollkreis zurück zum Abschnitt 8.5.4 , wo wir angefangen haben.

    
Shafik Yaghmour 07.07.2015 20:18
quelle