it-swarm.com.de

Warum verwenden C ++ - Vorlagen die Syntax von spitzen Klammern?

Die Titelfrage bezieht sich auf die Entwurfsentscheidungen im C++ - Standard, mit denen Vorlagen um 1990 eingeführt wurden.

Warum haben die Designer <> (spitze Klammern) anstelle von () (runde Klammern)? Dies hätte viele Programmierer vor dem Bitverschiebungsfehler bewahrt

std::vector<std::vector<int>> // does not work until C++11

das wurde nur in C++ 11 behoben. Ich sehe keinen Grund für die Einführung einer solchen zusätzlichen Syntax, wenn runde Klammern vermutlich den gleichen Zweck erfüllt hätten, während die Änderungen minimal gehalten worden wären. Insted hättest du gebrauchen können

template(typename T) // Define template if round brackets could be used
mytemplate { ... }
...
...
mytemplate(mytemplate(int)) obj; //Instantiate template when round brackets could be used

Kann jemand, der mit der Geschichte von C++ vertraut ist, die ursprünglichen Gründe für die Verwendung von spitzen Klammern herausfinden? Können Sie alternativ zeigen, warum andere Lösungen nicht so gut funktioniert hätten?

41
shuhalo

Die Vorlagen wurden 1988 in der USENIX-Veröffentlichung Parametrized Types for C++ von Bjarne Stroustrup vorgestellt, die später in The Annotated C++ Reference Manual veröffentlicht wurde 1990 (die Version vor standardisiertem C++). Nach dem Papier,

Die Klammern <…> Werden den Klammern (…) Vorgezogen, um die unterschiedliche Art von Vorlagenargumenten hervorzuheben (sie werden beim Kompilieren ausgewertet) ) und teilweise, weil Klammern in C++ bereits hoffnungslos überstrapaziert sind.

9.2. <…> Vs (…)

Aber warum Klammern anstelle von Klammern verwenden? Wie bereits erwähnt, haben Klammern in C++ bereits viele Verwendungsmöglichkeiten. Ein syntaktischer Hinweis (die Klammern <…>) Kann hilfreich sein, um den Benutzer an die unterschiedliche Art der Typparameter zu erinnern (sie werden zur Kompilierungszeit ausgewertet) . Darüber hinaus könnte die Verwendung von Klammern zu ziemlich obskurem Code führen:

template(int sz = 20) class buffer {
    buffer(int i = 10);
    // ...
};
buffer b1(100)(200);
buffer b2(100);      // b2(100)(10) or b2(20)(100)?
buffer b3;           // legal?

Diese Probleme würden ein ernstes praktisches Problem werden, wenn die Notation zur expliziten Disambiguierung überladener Funktionsaufrufe übernommen würde. Die gewählte Alternative scheint viel sauberer:

template<int sz = 20> class buffer {
    buffer(sz)(int i = 10);
    // ...
};
buffer b1<100>(200);
buffer b2<100>;      // b2<100>(10)
buffer b3;           // b3<20>(10)
buffer b4(100);      // b4<20>(100)

In dem Artikel wurde auch erläutert, warum die Schlüsselwörter template und class verwendet werden.

Beachten Sie, dass der Stroustrup den <…> after Variablennamen auf die gleiche Weise wie int x[10] Platziert hat, um gegen (…) Zu argumentieren, obwohl dies die Platzierung ist nie anderswo in der Zeitung verwendet.

Sein Argument, dass die Verwendung von (…) Zu undeutlichem/mehrdeutigem Code führen kann, ist jedoch weiterhin gültig. Wie im Kommentar zu dieser Frage erwähnt, führt die Verwendung von T(x) in Klammern zu Mehrdeutigkeiten beim Funktionstyp oder Funktionsaufruf (beachten Sie, dass T eine Funktionsvorlage sein kann und C++ zulässige Werte Vorlagenargumente sein können).

Ebenso führt die Verwendung von eckigen Klammern T[x] Zu Mehrdeutigkeiten beim Array-Typ oder der Indizierung.

Ich verstehe nicht, warum T{x} Noch nicht verwendet werden kann, vielleicht wurde es einfach nicht berücksichtigt, oder vielleicht ist es zu hässlich, um {…} Überall zu verwenden.

96
kennytm