Vorlagefunktion des Vorlagenobjekts und Namespaces

8

Im folgenden C ++ - Beispielcode stimmen GCC 6 und Clang 3.8 nicht überein, was das richtige Verhalten ist:

Dieses konstruierte Beispiel "funktioniert" - wie in der Funktion test() gibt o.p in GCC zurück. In clang ruft es die (undefinierte) Funktion get<int, int, float, double> :

auf %Vor%

Wenn der gleiche Code in einen Namespace eingefügt wird, bewirkt GCC, dass er das gleiche tut, was call tut.

%Vor%

Ссылка und Ссылка

Welcher Compiler ist "korrekt" und gibt es im Allgemeinen eine Möglichkeit, zu definieren ein Freund Mitglied Vorlage Funktion inline, ohne es zu deklarieren und dann separat definieren. Das sind Dinge wie:

%Vor%     
Matt G 19.04.2016, 15:11
quelle

1 Antwort

5

Es gibt zwei ungelöste Probleme in Bezug auf friend -Funktionsvorlagen, die in Klassenvorlagen definiert sind: 1545 und 2174 . Ersteres stellt die Frage, inwieweit es überhaupt gültig ist, und letzteres geht um odr-Verstöße, die aufgrund der tatsächlichen Instanziierungen dieser Funktionsvorlagen entstehen können. Ich bin mir nicht sicher, welcher Compiler richtig ist (bisher war ich der Meinung, dass beide falsch waren), aber im Standard ist es einfach zu schlecht oder schlecht spezifiziert, was das richtige Verhalten in dieser Situation ist.

Der Code sollte idealerweise kompilieren (offene Problemauflösung):

%Vor%

Die friend -Deklaration deklariert zuerst get , so dass dies ein neues Mitglied des innersten einschließenden Namespace erzeugt: ::get . Die externe Deklaration dekodiert einfach die gleiche Funktion, also gibt es wirklich nur die eine ::get . Aus [temp.over.link]:

  

Zwei Ausdrücke, die Template-Parameter enthalten, werden als äquivalent angesehen, wenn zwei Funktionsdefinitionen enthalten sind   Die Ausdrücke würden die Definition für eine Definition (3.2) erfüllen, außer dass die Token, die verwendet werden, um die   Vorlagenparameter können sich unterscheiden, solange ein Token verwendet wird, um einen Vorlagenparameter in einem Ausdruck zu benennen   durch ein anderes Token ersetzt, das denselben Template-Parameter in dem anderen Ausdruck benennt. Zum Bestimmen   ob zwei abhängige Namen (14.6.2) äquivalent sind, wird nur der Name selbst betrachtet, nicht das Ergebnis der Namenssuche im Kontext der Vorlage.

Die Verwendung verschiedener Vorlagenparameternamen ( Args... vs Args2... ) ist in Ordnung - diese zweite Deklaration der Funktionsvorlage ::get ist gültig und ermöglicht die Suche, um sie zu finden.

Das bringt uns zu:

%Vor%

Diese beiden sollten funktionieren - da wir die Funktion im Namespace-Bereich umbenannt haben, brauchen wir uns nicht einmal um ADL zu kümmern. Beide Aufrufe sollten ::get<int>(obj<int, float, double> ) finden, was ein friend ist, und daher sollte der Code kompiliert und verlinkt werden. gcc erlaubt den unqualifizierten Anruf, aber nicht den qualifizierten Anruf, clang erlaubt es auch nicht.

Wir könnten beide CWG-Probleme vollständig umgehen, indem wir not die Funktionsvorlage in der Klasse definieren:

%Vor%

Mit dieser Formulierung erlauben beide Kompilierungen sowohl qualifizierten als auch unqualifizierten Aufruf von get .

Wenn wir den Code so schreiben, dass obj eine Klasse und keine Klassenvorlage ist, aber alles andere gleich ist:

%Vor%

Beide Compiler erlauben beide Aufrufe. Aber es gibt keinen Unterschied, den ich in den Regeln zwischen obj als normaler Klasse und einer Klassenvorlage kenne.

    
Barry 19.04.2016, 17:17
quelle