2014-10-25 1 views
5

Der folgende Code kompiliert erfolgreich mit Klirren 3.5.0 und g ++ 4.9.0 (mit -Wall -Wextra -pedantic-errors flags) unter C++03 (flag -std=C++03), C++11 (flag -std=C++11) und C++14 (flag -std=C++14):Zusätzliches Schlüsselwort type in der Vorlagenparameterliste: Ist es gültig oder nicht?

namespace N 
{ 
    typedef int T; 

    enum E{}; 
} 

template <typename N::T> 
struct ST{}; 

template <typename N::E> 
struct SE{}; 

int main() 
{ 
} 

Ist es gültig zusätzliche typename Keyword hinzufügen vor einer Nicht-Typ-Template-Parameter-Deklaration?


Beachten Sie, dass der folgende Code kompiliert nicht (wie C++03, C++11 und C++14 code):

typedef int T; 

enum E{}; 

template <typename T t> 
struct ST{}; 

template <typename E e> 
struct SE{}; 

int main() 
{ 
} 

Aber das folgende kompiliert wieder in Ordnung (C++03, C++11 und C++14) :

typedef int T; 

enum E{}; 

template <typename ::T> 
struct ST{}; 

template <typename ::E> 
struct SE{}; 

int main() 
{ 
} 
+0

Ich vermute, dass 'typename N :: T' geparsed als ein Typparameter, nicht verwandt mit dem tatsächlichen Typ' N :: T'. Der Name ist jedoch seltsam. – leemes

+0

@dyp Und was sollte aus Ihrem Angebot folgen? – Constructor

+0

@leemes Ja, das denke ich auch. Und es ist * sehr * seltsam. – Constructor

Antwort

6

Es ist erlaubt, aber nur mit qualifizierten Namen:

typename-Spezifizierer:
                  typenamenested-name-Spezifizierer Identifikator
                    typenameNested-name-Spezifizierer template opt einfach-template-ID

So ist typename E falsch gemäß der Grammatik. typename N::E ist nicht, da der Name qualifiziert ist. Der dritte Fall, typename ::E, ist in Ordnung, da :: ein gültiger Nested-Name-Specifier ist.

Die C++ 03-Standard spezifiziert in [temp.res]/5, daß

Das Schlüsselwort typename gilt nur für qualifizierte Namen angewendet werden, aber diese Namen müssen nicht abhängig.

Die C 11 ++ Standard besagt dies nirgends ausdrücklich, aber in einer Notiz in [temp.names]/5:

[Hinweis: Wie ist der Fall mit dem, typename Präfix ist die template Präfix ist erlaubt, wenn es nicht unbedingt notwendig ist; d.h. , wenn der verschachtelten-name-specifier oder der Ausdruck auf der linken Seite der -> oder . auf einem Template-Parametern abhängig ist oder die Verwendung nicht im Rahmen einer Vorlage angezeigt wird. - Endnote]

Die gleiche Note gibt es in der exakt gleichen Stelle in der Standard-14 C++.

+0

Also, wenn der Name nicht abhängig ist, dann ist Typname überflüssig? – 0x499602D2

+0

@ 0x499602D2 Ja. 'typename' steht für Disambiguierung; Wenn keine Disambiguierung erforderlich ist, ist 'typename' nicht erforderlich;) – dyp

+0

@ 0x499602D2 Sicher. – Columbo

Verwandte Themen