Warum wurde für Konstruktoren, die eine std :: initializer_list verwenden, keine Syntax für doppelte geschweifte Klammern bevorzugt?

Einheitliche Initialisierung ist eine wichtige und nützliche C ++ 11-Funktion. Sie können jedoch nicht nur verwenden{} überall seit:

std::vector<int> a(10, 0);    // 10 elements of value zero
std::vector<int> b({10, 0});  // 2 elements of value 10 and 0 respectively
std::vector<int> c{10, 0};    // 2 elements of value 10 and 0 respectively
std::vector<int> d = {10, 0}; // 2 elements of value 10 and 0 respectively

auto e(0);    // deduced type is int
auto f = 0;   // deduced type is int
auto g{0};    // deduced type is std::initializer_list<int>
auto h = {0}; // deduced type is std::initializer_list<int>

Bemerken, dassGesamtinitialisierung auf z.B.std::arrays erfordert die Verwendung von{{}}Mir scheint, das ganze Problem mitWelcher Vektorkonstruktor wird ausgewählt? hätte vermieden werden können, indem man a{{}} Konstrukteure anrufen unter astd::initializer_list:

std::vector<int> i{10, 0};    // 10 elements of value zero
std::vector<int> j{{10, 0}};  // 2 elements of value 10 and 0 respectively
std::vector<int> k = {10, 0}; // 2 elements of value 10 and 0 respectively

auto l{0};    // deduced type is int
auto m{{0}};  // deduced type is std::initializer_list<int>
auto n = {0}; // deduced type is std::initializer_list<int>

Ich bin sicher, das wurde diskutiert. Was waren die Gründe dagegen? Als Antwort wird ein Zitat / Link aus einem Standardvorschlag bevorzugt.

Aktualisieren. - Es gibt einen Punkt inN2532 das besagt:

(3) Die wahrscheinlich unangenehmen Mehrdeutigkeitsfälle treten nur bei kurzen Initialisierungslisten auf [...]

(5) Warum sollten die Sprachregeln Programmierer zwingen, die (aus absolut guten Gründen) Knappheits- und Mehrdeutigkeitskontrolle wünschen, mehr zu schreiben, um Programmierern zu gefallen, die (aus absolut guten Gründen) es vorziehen - und können?

[...]

Angenommen, ein Programmierer erwartet, dass f (X) aufgerufen wird. Wie könnte ein f (Y) einen Anruf „entführen“?

(4) Angenommen, X hat keinen Konstruktor für die Initialisierungsliste, Y jedoch. In diesem Fall wird der Hijacker von den Initialisierer-Listen-Konstruktoren bevorzugt (denken Sie daran, dass wir angenommen haben, dass der Programmierer erwartet hat, dass f (X) aufgerufen wird). Dies ist analog zu jemandem, der erwartet, dass f (y) f (X) mit einer benutzerdefinierten Konvertierung aufruft, und jemand kommt mit einem genau passenden f (Y).Ich denke, es wäre fair zu erwarten, dass sich jemand, der {…} verwendet, an die Möglichkeit erinnert, Konstruktoren mit Initialisierungslisten zu erstellen. [Hervorhebung von mir]

Ich denke der Schlüssel liegt in derkann seinDies bedeutet, dass Sie keine einheitliche Initialisierung verwenden müssen. Verwenden{} richtig ist schwer da:

Sie müssen nicht nur nach dem Konstruktor suchen, den Sie aufrufen möchten, sondern auch nachirgendein Konstruktor unter eineminitializer_list das könnte siegen (und wird es wahrscheinlich);

Wenn Sie Code mit schreiben{} und jemand in der Zukunft fügt einstd::initializer_list Konstruktor Ihr Code könnte brechen und dies tunschweigend.

Auch wenn Sie eine Klasse habenA mit den KonstrukteurenA(int, bool) undA(std::initializer_list<double>), letzteres wird vor erstem für ausgewähltA a{0, false}; (welche IMO ist verrückt), so finde ich esJa wirklich Es ist schwierig, eine einheitliche Initialisierung für Klassen mit oder zu verwendenkönnte haben (Kristallkugel Superkräfte erforderlich)initializer_list Konstrukteure.

Die Tatsache, dass Ihr Code unbemerkt kaputt gehen kann, bereitet mir große Sorgen.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage