Ich bekomme konsistentes Verhalten sowohl von gcc 4.8.3 und clang 3.2, verstehe aber nicht, warum es passiert. Trotz der Tatsache, dass ich eine explizite Instanziierung für eine Klassenvorlage habe, wird der Code nicht generiert und ich erhalte ein undefiniertes Symbol, wenn ich eine vollständig spezialisierte Instanz der Vorlage verwende.Kein generierter Code für explizit spezialisiertes Template auch bei expliziter Instanziierung
Ich habe eine einfache Klasse Template-Definition in einer Datei 'temp.hpp'
#pragma once
template <typename T1>
class C
{
public:
C (T1 c) : d_c(c) {};
~C() = default;
void print();
private:
T1 d_c;
};
Beachten Sie, dass die Methode 'print()' deklariert wird, aber nicht definiert. Ich möchte die Definition in der .cpp-Datei und es wird für verschiedene Typen spezialisiert sein.
So in der temp.cpp Datei habe ich die Standarddefinition des print() Methode
#include "temp.hpp"
#include <iostream>
template<typename T1>
void
C<T1>::print()
{
std::cout << "Printing: " << d_c << std::endl;
}
durch eine Spezialisierung der Klasse für den Typ 'schweben' gefolgt:
template <>
class C <float>
{
public:
C (float f) : d_f(f) {};
~C() = default;
void print()
{
std::cout << "float: " << d_f << std::endl;
}
private:
float d_f;
};
und da die Definitionen in der .cpp-Datei sind, muss ich explizit alle Spezialisierungen instanziieren, die ich verwenden werde. Also ich habe:
template class C<int>;
template class C<float>;
Der Treiber für meinen Test wie dies in test.cpp aussieht:
#include "temp.hpp"
int main()
{
int i = 1;
C<int> c_int(i);
float f = 1.2;
C<float> c_float(f);
c_int.print();
c_float.print();
}
Beim Kompilieren und Linken das ich Fehler:
test.cpp: undefined reference to `C<float>::print()'
Der Objektcode für die C < int> wird ordnungsgemäß generiert. Ich kann es nm sehen:
nm -C temp.o
...
0000000000000000 W C<int>::print()
0000000000000000 W C<int>::C(int)
0000000000000000 W C<int>::C(int)
...
Wie ich bereits erwähnt, ist dies im Einklang mit gcc und Klirren so gehe davon aus ich dort einige Sprachregel ist verstehe ich nicht hier.
Beachten Sie, dass, wenn ich eine Verwendung der print() -Methode in der Datei temp.cpp hinzufügen, dann wird der Code generiert, aber das ist albern und in meinem echten Code wäre unmöglich. Für diesen einfachen Testfall würde es wie folgt aussehen:
void foo()
{
C<float> s(1.3);
s.print();
}
In der realen Code, der diesen kleinen Test motiviert meine Vorlage 3 Vorlage Argumente hat, die in etwa 30 Permutationen des Codes erweitern kombinieren. Es gibt ein oder zwei von denen, für die ich eine Spezialisierung brauche, die etwas anderes macht, aber die anderen 28 kann ich in Ruhe lassen.
Irgendwelche Hinweise darauf, wo ich falsch gelaufen bin oder eine Sprachreferenz dafür, warum die explizite Instanziierung von Code keinen Code generiert, werden sehr geschätzt. Ich habe einen halben Tag damit verbracht, alle anderen Stack-Overflow-Posts bei expliziter Instanziierung zu lesen und glaube, dass ich sie richtig verwende.
So Sie die Spezialisierung für 'C' in 'temp.cpp' haben, aber Sie wollen in' test.cpp' diese Spezialisierung benutzen? Das ist ein Problem. Der spezialisierte Typ 'C ' ist ein anderer und völlig nicht verwandter Typ von dem, was Sie bekommen würden, wenn Sie 'float' für' T1' in der ursprünglichen Vorlage ersetzen würden. In 'test.cpp' sucht es nach' C :: print() 'wo' T1 == float', und das ist nicht in Ihrem Programm vorhanden. Wenn Sie die Spezialisierung in die Kopfzeile 'temp.hpp' verschieben, sollte es funktionieren; Die Spezialisierung muss für den Compiler sichtbar sein, wenn "test.cpp" verarbeitet wird. –
Danke für die Erklärung Jason, im echten Code ist die Menge an Code in der Spezialisierung ausreichend komplex, dass es in einer Menge anderer Header-Dateien gezeichnet würde, und ich würde zum Zwecke der Kompilierung im Header Hades landen. Ich habe eine alternative Lösung gefunden, bei der ich die Erweiterungen, die illegalen Code generieren, weiter oben in der Erweiterungshierarchie halten kann. – Jay