8

Vor kurzem schrieb ich eine sehr einfache Klasse.std :: initializer_list typ abzug

class C 
{ 
public: 
    void AddString(std::initializer_list<std::pair<const char*,int>> x) 
    { 
      //irrelevant 
    } 
}; 

int main() 
{ 
      C c; 
      c.AddString({ {"1",1}, {"2", 2}, {"3", 3} }); 
      .... //other unimportant stuff 
      return 0; 
} 

Zu meiner angenehmen Überraschung kompiliert und funktionierte es korrekt. Kann mir bitte jemand erklären, wie der Compiler in der Lage war, die verschachtelten abgestuften Initialisierer für eine std::pair abzuleiten? Ich bin mit MSVS 2013.

Antwort

9
c.AddString({ {"1",1}, {"2", 2}, {"3", 3} }); 

Sie vorbei eine verspannt-init-Liste, die sich verschachtelte Klammer-init-Liste s AddString enthält. Das Argument kann mit dem Parameter std::initializer_list<std::pair<const char*,int>> übereinstimmen, wenn die innere stained-init-Liste s in std::pair<const char*,int> konvertiert werden kann.

Dieser Prozess der Überladungsauflösung erfolgt in zwei Schritten; Zuerst wird versucht, Konstruktoren von std::pair zu finden, die ein std::initializer_list Argument verwenden. Da std::pair keinen solchen Konstruktor aufweist, tritt der zweite Schritt auf, wobei die anderen Konstruktoren von std::pair<const char*,int> mit char const[2] und int als Argumente aufgezählt werden. Dies entspricht dem folgenden pair-Konstruktor, da char const[2] implizit in char const * konvertiert werden kann und der Konstruktor selbst nicht explicit ist.

template< class U1, class U2 > 
constexpr pair(U1&& x, U2&& y); 

N3337 Zitiert §13.3.1.7/1 [over.match.list]

Wenn Objekte von nicht-aggregierte Klassentyp T sind Liste initialisiert (8.5.4), wählt die Überladungsauflösung den Konstruktor in zwei Phasen aus: — Anfänglich sind die Kandidatenfunktionen die Initialisierungslistenkonstruktoren (8.5.4) der Klasse T und die Argumentliste besteht aus der Initialisierung er listet als einzelnes Argument auf.
Wenn kein ausführbarer Initialisierungslistenkonstruktor gefunden wird, wird die Überladungsauflösung erneut ausgeführt, wobei die Kandidatenfunktionen alle Konstruktoren der Klasse T sind und die Argumentliste aus den Elementen der Initialisierungsliste besteht.

Wenn die Initialisierungsliste keine Elemente enthält und T einen Standardkonstruktor hat, wird die erste Phase weggelassen. Wenn in der Kopierlisten-Initialisierung ein explicit-Konstruktor ausgewählt wird, ist die Initialisierung fehlerhaft.

+0

Große Antwort, viel vollständiger! – vsoftco

+0

Danke, das klärt einige Dinge ... Ich muss ein bisschen mehr über Überlast-Auflösung verstehen, wenn verspannte Init-Listen beteiligt sind. – pebbleonthebeach

+0

@pebbleonthebeach Die Regeln für die Überladungsauflösung bei der Listeninitialisierung sind die, die ich oben eingefügt habe. Wenn Sie meinen, dass Sie sich mit der Überladungsauflösung im Allgemeinen vertraut machen müssen, schlage ich vor, dass Sie mit [diesem Video] beginnen (https://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-)./Stephan-T-Lavavej-Kern-Cpp-3-of-n) (sehen Sie die ganze Reihe, wenn Sie die Zeit finden können). – Praetorian