Vorlagenfunktionen im Namespace verursachen Fehler

8

Nehmen Sie den folgenden Code an:

%Vor%

Aus irgendeinem Grund, den ich nicht verstehen kann, erzeugt es die folgenden Kompilierungsfehler mit g++-4.8 :

%Vor%

während clang 3.3 ergibt:

%Vor%

Wenn jedoch der Namespace Utils entfernt wird, kompiliert er ohne Fehler (sowohl gcc und clang) als auch Ausführungsausführungen:

%Vor%

Warum verursacht die Definition dieser Vorlagenfunktionen ( RemoveLinks ) in einem Namespace solche Fehler?

    
Allan 28.08.2013, 16:51
quelle

2 Antworten

7

Dieses Problem ist ein Ergebnis eines Problems mit dem Punkt der Deklaration (1) kombiniert mit abhängiger Namenssuche (2).

(1) In der Deklaration

%Vor%

Der Name RemoveLinks , genauer gesagt, diese Überladung von RemoveLinks , ist nur sichtbar nach dem vollständigen Deklarator gemäß [basic.scope.pdecl] / 1. Der trailing-return-type ist gemäß [dcl.decl] / 4 Teil des Deklarators. Siehe auch diese Antwort .

(2) In dem Ausdruck RemoveLinks(link.val) ist der Name RemoveLinks abhängig von [temp.dep] / 1, da link.val abhängig ist.

Wenn wir nun nachsehen, wie abhängige Namen aufgelöst werden, finden wir [temp.dep.res]:

  

Bei der Auflösung abhängiger Namen werden Namen aus folgenden Quellen berücksichtigt:

     
  • Deklarationen, die zum Zeitpunkt der Definition der Vorlage sichtbar sind.
  •   
  • Deklarationen aus Namespaces, die den Typen der Funktionsargumente sowohl aus dem Instanziierungskontext als auch aus dem Definitionskontext zugeordnet sind.
  •   

Der erste Punkt findet die zweite Überladung von RemoveLinks wegen des Punktes der Deklaration (1) nicht. Die zweite findet die Überladung nicht, da der Namespace Util keinem Argument zugeordnet ist. Aus diesem Grund funktioniert alles im globalen Namespace oder im Namespace Util wie erwartet ( Live-Beispiel ).

Aus dem gleichen Grund hilft die Verwendung einer qualifizierten ID im trailing-return-type (wie -> decltype(Util::RemoveLinks(link.val)) hier nicht.

    
dyp 29.08.2013 16:25
quelle
2

Ich habe versucht, den obigen Beispielcode mit GCC 4.8.1, mit clang und auch Intel iccp zu kompilieren und habe die gleichen Fehlermeldungen erhalten wie du.

Ich kann es problemlos kompilieren, wenn ich die Signatur der Template-Spezialisierung von:

überarbeite %Vor%

und mache den Rückgabetyp als const. Dies könnte zu einer Compilerwarnung führen, da die Konstante dort bedeutungslos ist, aber das kann ignoriert werden. Ich habe es getestet und es funktioniert gut für mich mit gcc, aber nicht icpc oder clang:

%Vor%

Ich fand die Fehlermeldung (mit dem Originalcode) von Intel icpc am informativsten:

code.cc (48): Fehler: Die Template-Instanziierung führte zu einem unerwarteten Funktionstyp von " auto (const Link<Link<int &>> &)->const int & " (die Bedeutung eines Namens könnte sich seit der Template-Deklaration geändert haben - der Typ der Vorlage ist " auto (const Link<T> &)->decltype((<expression>)) ") %Code%                                                 ^           bei der Instanziierung von "Utils :: RemoveLinks" basierend auf dem Template-Argument std::cout << Utils::RemoveLinks(link) << std::endl; in Zeile 48

gefunden

Leider ist die obige Antwort eher eine Problemumgehung für gcc als eine Antwort auf Ihre Frage. Ich werde dies aktualisieren, wenn ich etwas mehr / besser hinzufügen kann.

BEARBEITEN

Es scheint, dass declltype (RemoveLinks (link.val)) tatsächlich der Rekursion folgt, so dass es int & amp; anstatt Link.

BEARBEITEN # 2

Es wurden Fehler in LLVM über Abstürze gemeldet, die durch Dekrentyp-Rekursionsprobleme verursacht wurden. Es scheint, dass dies definitiv ein Fehler ist, aber einer, der in mehreren Implementierungen von C ++ zu sein scheint.

Das Problem kann relativ einfach behoben werden, wenn Sie in der Link-Struktur einen Alias ​​für Typ T erstellen und declltyp sich auf den Alias ​​und nicht auf den Rückgabetyp bezieht. Dies wird die Rekursion beseitigen. Wie folgt:

%Vor%

Und dann wird die RemoveLinks-Signatur entsprechend geändert, um auf diesen Alias ​​zu verweisen:

%Vor%

Dieser Code baut erfolgreich auf allen 3 Compilern auf.

Ich werde einige Fehlerberichte mit den Compilern einreichen, um zu sehen, ob sie etwas dagegen tun können.

Hoffe, das hilft.

    
Shmuel Levine 29.08.2013 13:55
quelle