LNK2019 (VS 2008) mit vollständiger Implementierung der Template-Funktion mit Template-Funktionszeigern

8

Der folgende minimale Code kompiliert und verlinkt in GNU C ++:

%Vor%

, aber mit Visual Studio 2008 wird der Fehler

erzeugt %Vor%

Offensichtlich ist die ganze Funktionsimplementierung da, aber es scheint, dass der Compiler die Implementierung der Funktion foo wegwirft. Wenn die kommentierte Zeile aktiviert ist, findet der Linker das Symbol.

Ich denke (wie g ++ es gut kompiliert), das ist ein gültiger Code, also nehme ich an, dass es einen Fehler in VS 2008 gibt, oder mache ich hier etwas falsch? Kennt jemand eine Workaround / Lösung dafür? Der letzte Code muss mit Visual Studio 2008 arbeiten und im realen Code ist es nicht möglich, alle Template-Typ-Kombinationen zu erraten (dh ich kann die Funktionen nicht explizit für alle verfügbaren Typen instanziieren: hier nur T, im echten Code bis zu Es werden 5 Template-Parameter mit beliebigen Klassen verwendet.)

    
JPAM69 26.06.2014, 15:10
quelle

1 Antwort

4

Ursprüngliche Frage

Als Antwort auf die ursprüngliche Frage; Ist das ein Fehler, gibt es Problemumgehungen?

Ja, es sieht so aus, als hätten Sie einen Fehler in VS2008 gefunden, ich habe ihn mit VS2008 und VS2013.2 mit dem gleichen Linker-Fehler getestet. Ich möchte Sie ermutigen, einen Fehlerbericht mit Microsoft einzureichen. Gibt es Workarounds, glaube ich, könnte es sein.

Wie Sie bemerkt haben, sieht es so aus, als ob der Compiler die implizite Instanziierung des Templates foo<int> irgendwo zwischen dem Zerfall zu void (*Function)(T,void*) und dem Zeitpunkt, zu dem er zur Verbindungszeit benötigt wird, "verliert". Nachdem ich mit dem Code ein bisschen herumgespielt habe, denke ich, dass es die apply(M) Vorlage und Microsoft's Template Parsing Techniken beinhalten könnte; da, wenn apply nur ein int als Argument apply(int) (d. h. keine Vorlage) benötigt, scheint es glücklich zu sein, es zu kompilieren und zu verknüpfen.

Um dies zu umgehen, kann der Code wie folgt geändert werden (Hinzufügen des Standardkonstruktors und Ändern des apply -Aufrufs von einer Instanz von kernel ). Ich weiß, das kann hässlich aussehen; aber es funktioniert um das Problem und kann Ihnen helfen, das Problem in Ihrem Projekt zu umgehen.

%Vor%

Der Code kompiliert und verbindet sich mit VS2008, VS2013 und gcc.

Wie funktioniert der Code mit modernen Compilern?

Mit Bezug auf die Kommentare zur ursprünglichen Frage; Warum oder wie funktioniert das mit einem modernen Compiler? Es handelt sich um zwei C ++ - Einrichtungen.

  1. Funktionszeiger-Zerfall
    • Gegebenenfalls mit zusätzlichen Regeln (z. B. Vorlagen)
  2. Implizite Funktion Template Instanziierung

Wenn foo als Argument für void(*Function)(T,void*) angegeben wird, findet ein Decay statt und ein Zeiger wird verwendet, als wäre &foo verwendet worden.

  

Konvertierung von Funktion zu Zeiger 4.3

     

1 Ein Wert des Funktionstyps T kann in einen Pr-Wert vom Typ "Zeiger auf T" umgewandelt werden. Das Ergebnis ist ein Zeiger auf die Funktion

Funktion-Zeiger-Konvertierungen verweisen auf Abschnitt 13.4 für zusätzliche Regeln, wenn möglicherweise überladene Funktionen vorhanden sind. Beachten Sie die Details zur Verwendung von & und den Fall, in dem die Funktion eine Vorlage ist (Hervorhebung meins).

  

Adresse der überladenen Funktion 13.4

     

1 Es wird angenommen, dass ein Funktionsschablonenname einen Satz überladener Funktionen bezeichnet ... Dem überladenen Funktionsnamen kann das & amp; Operator .

     

2 Wenn der Name eine Funktionsvorlage ist, wird Vorlagenargumentabzug durchgeführt (14.8.2.2), und wenn die Argumentableitung erfolgreich ist, wird die resultierende Vorlagenargumentliste zum Generieren einer einzelnen Funktionsvorlage verwendet Spezialisierung, die zu der Menge der überladenen Funktionen hinzugefügt wird.

Gegeben sei der Zeiger und die Ableitung des Compilers vom Typ T für die Funktion foo in diesem Fall int . Der Compiler erzeugt dann den Code für die Funktion void foo(int,void*) und dann wird dies während des Linkens verwendet.

  

Implizite Instanziierung 14.7.1

     

3 Sofern eine Funktionsschablonenspezialisierung nicht explizit instanziiert oder explizit spezialisiert wurde, wird die Funktionsschablonenspezialisierung implizit instanziiert, wenn auf die Spezialisierung in einem Kontext verwiesen wird, der die Existenz einer Funktionsdefinition erfordert.

Zitate aus C ++ WD n3797

    
Niall 08.07.2014, 11:17
quelle