Sowohl clang als auch gcc lehnen diesen Code ab:
%Vor%Beide akzeptieren jedoch den folgenden Code:
%Vor% Der Standard besagt, dass die Namenssuche eines Namens vor ::
"nur Namespaces, Typen und Vorlagen berücksichtigt, deren Spezialisierungen Typen sind". Sind clang und gcc bei der Ablehnung dieses Codes korrekt? Wenn ja, was fehlt mir?
Aus C ++ Working Draft Standard n3337
3.4.3 Suche nach qualifizierten Namen [basic.lookup.qual]
Auf den Namen eines Klassen- oder Namespace-Members oder -Enumerators kann nach der :: scope-Auflösung verwiesen werden Operator (5.1) angewendet auf einen Nested-Name-Specifier, der seine Klasse, seinen Namespace oder seine Enumeration bezeichnet. Wenn ein :: Dem Scope-Auflösungsoperator in einem Nested-Name-Specifier steht kein Dekletyp-Specifier, Lookup des Der vorangestellte Name :: berücksichtigt nur Namespaces, Typen und Vorlagen, deren Spezialisierungen Typen sind . Wenn der gefundene Name keinen Namespace oder eine Klasse, eine Enumeration oder einen abhängigen Typ angibt, wird das Programm verwendet ist schlecht gebildet.
14.2 Namen von Vorlagenspezialisierungen [Temp.Name]
Damit ein Vorlagenname explizit durch die Vorlagenargumente qualifiziert wird, muss der Name bekannt sein, auf den verwiesen wird zu einer Vorlage .
Nach der Namenssuche (3.4) wird festgestellt, dass ein Name ein Schablonenname ist oder dass sich eine Operatorfunktions-ID oder eine Literaloperator-ID auf eine Gruppe von überladenen Funktionen bezieht, von denen jedes Mitglied ist Das ist eine Funktionsvorlage , wenn dies der Fall ist gefolgt von einem
<
, wird der<
immer als Trennzeichen einer Template-Argument-Liste und niemals als Kleiner-als genommen Operator .
Um eine Verwechslung dieses Problems mit der Mehrdeutigkeit zwischen einem Ausdruck und einer Deklaration zu vermeiden, ist hier der ursprüngliche Code mit den Vorlagen, die einen Typparameter anstelle eines Nichttypparameters verwenden.
%Vor% Dies führt in allen Fällen zum gleichen Fehler. Der <
kann nicht als Operator interpretiert werden.
ambiguous
ist eindeutig ein Vorlagenname, könnte aber auch ein Typ oder eine Funktion sein. Es ist möglich, die gesamte Vorlagen-ID zu analysieren, ohne zu wissen, ob sie eine Funktion oder einen Typ benennt, und später die Mehrdeutigkeit aufzulösen. Entschuldigt der Standard den Implementierer davon?
Das Problem ist, dass der Absatz, den du zitierst, endet
zu spät angewendet. Bevor es dorthin kommt, muss der Compiler
Bestimmen Sie, dass in ambiguous<3>::value
, <
und >
sind
Vorlage Argument Trennzeichen, und nicht größer als und weniger
als. (Überlegen Sie:
, die als (ambiguous < 3) > ::value
analysiert, wobei <
und
>
sind kleiner als bzw. größer als.) Dies
beinhaltet eine Suche von ambiguous
als nicht qualifizierten Namen und
bindet das Symbol an N::ambiguous
. Danach steckst du fest
mit der instanziierten Vorlage N::ambiguous<3>
links von
::
, was nicht legal ist.
Dieses Problem ist nicht so klar, wie man es mag: nur der Standard
bezieht sich auf Abschnitt 3.4 in Abschnitt 14.2, wo es diskutiert,
und Abschnitt 3.4 diskutiert alle möglichen Regeln des Namens
Sieh nach oben. Auf der anderen Seite gibt es wirklich nur einen Weg
interpretiere es: Der Compiler kann bis dahin nichts weiter analysieren
es weiß, ob ambiguous
eine Vorlage benennt oder nicht, und kann
Entscheiden Sie, ob das folgende <
größer als ist oder öffnet
eine Vorlagenargumentliste Und natürlich kann es das nicht "neu binden"
Argument später, nachdem es die folgenden Token geparst hat, seit
Im allgemeinen Fall könnte das erneute Binden die Bedeutung des
<
, wodurch die Syntaxanalyse ungültig wird. In der Praxis, obwohl der Standard
sagt nicht so klar, wie es wahrscheinlich sein sollte, den Namen Lookup
In diesem Fall muss ein unqualifizierter Name Lookup (oder Klassenmitglied) sein
Zugriff, wenn dem Namen ein Operator .
oder ein Operator ->
vorangestellt ist.
Vorlagen im inneren Namensraum verbergen die Namen der äußeren.
%Vor%Tags und Links c++ templates language-lawyer