Ich habe eine Template-Klasse NB::B<T>
, die von einer Nicht-Template-Klasse NA::A
in einem Namespace abgeleitet ist. act<T>
ist eine Vorlagenfunktion, die add_ref
function für eine Instanz ihres Vorlagenarguments aufruft. Insbesondere act<NB::B<int>>
möchte add_ref
im Namensraum der Basis von NB::B
mithilfe von ADL finden. Das vollständige Beispiel folgt:
Dies kompiliert in gcc
(4.7.0). Und in Comeau
online. Jedoch schlägt clang
(3.1) fehl:
Gleichzeitig lautet der Standard:
3.4.2 / 2 ...
- Wenn T eine Vorlagen-ID ist, sind die zugehörigen Namespaces und Klassen der Namespace, in dem die Vorlage definiert ist. für Mitgliedervorlagen die Klasse der Mitgliedervorlage; die Namespaces und Klassen, die den Typen der Vorlagenargumente zugeordnet sind, die für die Parameter des Vorlagentyps bereitgestellt werden (mit Ausnahme der Vorlagenparameter); die Namespaces, in denen Vorlagenvorlagenargumente definiert sind; und die Klassen, in denen alle als Vorlagevorlagenargumente verwendeten Elementvorlagen definiert sind.
Überraschenderweise werden Vorlagenbasen nicht als Pfade zu zugeordneten Namespaces aufgelistet. Das Verhalten von clang
scheint also korrekt zu sein. Und Comeau
und gcc
akzeptieren falsches Programm.
Gleichzeitig gibt 3.4.2/3
an, dass using
in den Namespaces des Arguments keine Auswirkung haben:
Wenn ein assoziierter Namespace berücksichtigt wird, entspricht die Suche der Suche, die ausgeführt wird, wenn der zugeordnete Namespace als Qualifikationsmerkmal (3.4.3.2) verwendet wird, mit Ausnahme von:
- Alle using-Direktiven im zugehörigen Namespace werden ignoriert.
Aber wenn ich die using NA::add_ref
-Zeile auskommentiere clang
ist glücklich, den Test zu kompilieren.
Um mein Beispiel in praktische Perspektive zu bringen, können Sie denken, dass act
eine Methode von boost::intrusive_ptr
war, add_ref(A*)
war intrusive_ptr_add_ref(CBase*)
und B
war eine Vorlage, abgeleitet von der Basis CBase
.
In diesem Zusammenhang habe ich einige Fragen:
Habe ich Recht, dass clang
's korrekt ist, mein Testprogramm abzulehnen, und gcc
und Comeau
folgen nicht dem Standard?
Gibt es einen Grund, warum der Standard ein solches unpraktisches Verhalten spezifiziert (die Vorlagenklassenbasen als assoziierte Namespaces nicht zulassen)?
Ist clang
falsch akzeptiert mein Testprogramm mit der using NA::add_ref
-Direktive aufgrund von 3.4.2/3
?
Soll ich einen Fehler melden? :)
P.S. Ich habe die Sprachkompatibilität FAQ gelesen und dort keine Antwort gefunden.
Von n3337, was im Grunde C ++ 11 mit kleineren redaktionellen Änderungen ist, lautet die 3.4.2 / 2:
Für jeden Argumenttyp T im Funktionsaufruf [...] Die Mengen von Namespaces und Klassen werden folgendermaßen bestimmt: [...]
- Wenn T ein Klassentyp ist (einschließlich Unionen), sind die ihm zugeordneten Klassen: die Klasse selbst; die Klasse, der es angehört, falls vorhanden; und seine direkten und indirekten Basisklassen . Die zugehörigen Namespaces sind die Namespaces, deren zugehörige Klassen Mitglieder sind. Außerdem , wenn T eine Klassenvorlagenspezialisierung ist, ...
Und es geht dann mit dem im Grunde genommen gleichen Zitat weiter, das Sie in der Frage gepostet haben. Der wichtige Unterschied ist hier außerdem , was bedeutet, dass die Liste, die Sie angegeben haben (und ich weggelassen habe), zusätzlich zu den bereits erwähnten Namespaces existiert und die Namespaces enthält, deren Basisklasse ein Member ist .
Gcc und comeau haben Recht, und c ++ ++ ist falsch bei der Ablehnung des Codes.
& lt; gilt nicht & gt;
Clang ++ ist falsch bei der Ablehnung ohne using NA::add_ref
.
Ja, Sie sollten wahrscheinlich einen Fehler melden. Es scheint, dass es bereits gemeldet und behoben wurde.
Tags und Links c++ gcc clang templates argument-dependent-lookup