Warum muss ich in C ++ 20 nicht "Typname" vor einem abhängigen Typ angeben?

70

Dieses Codebit wurde in C ++ 20 (mit gcc 10.1) kompiliert, ohne das typenameSchlüsselwort vor dem abhängigen Typ zu verwenden std::vector<T>::iterator. Warum kompiliert es?

#include <vector>

template<typename T>
std::vector<T>::iterator // Why does this not require "typename" before it?
f() { return {}; }

int main() {
    auto fptr = &f<int>;
}

Code Spielplatz

Jake Schmidt
quelle
2
Ich bin ein wenig überrascht , dass der Standard es mehrdeutig finden würde (daher erforderlich typename), da (ich glaube , ...) es hat eine Art , dort zu sein. Vielleicht möchten Sie language-lawyerTag hinzufügen .
Eljay
4
In C ++ 20 können Sie die Verwendung von Typnamen entfernen.
Jarod42
3
@Eljay Es muss noch wissen, dass es sich um einen Typ handelt;) Es ist ein Teil davon, wie "dort" definiert / erkannt wird. Oder besser gesagt, früher.
Asteroiden mit Flügeln

Antworten:

62

Eine der neuen Funktionen in C ++ 20 ist Down withtypename .

In C ++ 17, Sie hatten das bieten typenamefast alle Schlüsselwort in abhängig Kontexten einen Typen von einem Wert eindeutig zu machen. In C ++ 20 ist diese Regel jedoch stark gelockert. In allen Kontexten, in denen Sie einen Typ benötigen , ist dertypename Schlüsselwort nicht mehr obligatorisch.

Ein solcher Kontext ist der Rückgabetyp einer Funktion im Klassenbereich, wie in Ihrem Beispiel. Andere enthalten den Typ in einer Elementdeklaration, den Typ auf der rechten Seite einer using-Deklaration, die Parameterdeklaration eines Lambda, den Typ, an den Sie übergeben static_castusw. Die vollständige Liste finden Sie im Dokument .


Fast alle, weil Basisspezifizierer und Mem-Initialisierer-IDs immer ausgeschlossen wurden, wie in:

template <typename T> struct X : T::type  { }; // always ok

Das ist in Ordnung, denn das muss ein Typ sein. Das Papier erweitert diese Logik einfach (nun, es muss ein Typ sein, also nehmen wir einfach an, dass es ein Typ ist) auf viel mehr Orte, die Typen sein müssen.

Barry
quelle
7
IIRC haben wir bereits in C ++ 11 für die Basisspezifizierer und mem-initializer- ids typename optional gemacht . Der ursprüngliche typenameVorschlag verbot es überall dort, wo es nicht erforderlich war, aber wir hielten es für harmlos, eine Redundanz zu akzeptieren typename.
MSalters
19

Aus der Referenz , aus c ++ 20, wird in Kontexten, in denen der abhängige Name eindeutig ein Typname ist, das typenameSchlüsselwort nicht mehr benötigt. Speziell:

Ein qualifizierter Name, der als Deklarationsspezifizierer in der (obersten) Deklarationsspezifizierer-Sequenz von: verwendet wird.

Eine einfache Deklaration oder Funktionsdefinition im Namespace-Bereich

cigien
quelle