Я получаю согласованное поведение как от gcc 4.8.3, так и от clang 3.2, но не понимаю, почему это происходит. Несмотря на то, что у меня есть явное инстанцирование для шаблона класса, код не создается, и я получаю неопределенный символ, когда я использую полностью специализированный экземпляр шаблона.Нет сгенерированного кода для явно специализированного шаблона даже при явном экземпляре
У меня есть простое определение шаблона класса в файле «» temp.hpp
#pragma once
template <typename T1>
class C
{
public:
C (T1 c) : d_c(c) {};
~C() = default;
void print();
private:
T1 d_c;
};
Обратите внимание, что "печать() метод объявлен, но не определен здесь. Я хочу определение в файле .cpp, и оно будет специализировано для разных типов.
Таким образом, в файле temp.cpp У меня есть определение по умолчанию метода печати()
#include "temp.hpp"
#include <iostream>
template<typename T1>
void
C<T1>::print()
{
std::cout << "Printing: " << d_c << std::endl;
}
с последующей специализацией класса для «поплавка» типа:
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;
};
и поскольку определения находятся в файле .cpp, я должен явно указать все специализации, которые я буду использовать. Поэтому у меня есть:
template class C<int>;
template class C<float>;
Драйвер для моего теста выглядит в test.cpp:
#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();
}
После компиляции и компоновки этого я получаю сообщение об ошибке:
test.cpp: undefined reference to `C<float>::print()'
Объект код для C < int> правильно сгенерирован. Я могу видеть его с помощью нм:
nm -C temp.o
...
0000000000000000 W C<int>::print()
0000000000000000 W C<int>::C(int)
0000000000000000 W C<int>::C(int)
...
Как я уже говорил ранее, это согласуется с НКУ и лязг поэтому я предполагаю, что есть какое-то правило языка я не понимаю здесь.
Обратите внимание, что если я добавлю использование метода print() в файл temp.cpp, тогда код будет создан, но это глупо и в моем реальном коде будет невозможно. Для этого простого теста это будет выглядеть так:
void foo()
{
C<float> s(1.3);
s.print();
}
В реальном коде, ставший этот небольшой тест мой шаблон имеет 3 аргументов шаблона, которые сочетают в себе расшириться в около 30 перестановок коды. Есть один или два из тех, для которых мне нужна специализация, которая делает что-то другое, а другое 28 я могу оставить в покое.
Любые указатели на то, где я поступил неправильно, или ссылку на язык, почему явное создание экземпляра не должно генерировать код. Я потратил 1/2 дня на чтение всех других сообщений stackoverflow при явной инстанцировании и считаю, что правильно их использую.
Таким образом, вы имеете специализацию 'C' в 'temp.cpp', но вы хотите использовать эту специализацию в' test.cpp'? Это проблема. Специализированный тип 'C ' является другим и совершенно несвязанным типом от того, что вы получили бы, если бы вы заменили 'float' на' T1' в исходном шаблоне. В 'test.cpp' он ищет' C :: print() 'где' T1 == float', и этого не существует в вашей программе. Если вы переместите специализацию в заголовок 'temp.hpp', тогда он должен работать; специализация должна быть видна компилятору при обработке 'test.cpp'. –
Спасибо за объяснение. Джейсон. В реальном коде количество кода в специализации достаточно сложное, чтобы оно было нарисовано в кучу других файлов заголовков, и я бы попал в заголовок Hades для целей компиляции. Я нашел альтернативное решение, в котором я могу хранить расширения, которые генерируют незаконный код, дальше иерархии расширения. – Jay