Явная специализация шаблона класса и заголовочные файлы
Есть три файла:
main.cpp:
#include "test.h"
int main()
{
A<int> ai;
ai.print();
A<double> ad;
ad.print();
A<char> ac;
ac.print();
return 0;
}
test.cpp:
#include <iostream>
#include "test.h"
template<typename Type>
void A<Type>::print()
{
std::cout << "some" << std::endl;
}
//template<>
//class A<int>
//{
//public:
// void print()
// {
// std::cout << "int" << std::endl;
// }
//};
template class A<int>;
template class A<double>;
template class A<char>;
test.h:
#ifndef TEST_H
#define TEST_H
template<typename Type>
class A
{
public:
void print();
};
#endif
Выводит на экран:
some
some
some
Я хочу сделать явную специлизацию шаблона класса A, для этого раскомментирую закоментрованные строки. Результат:
/usr/bin/ld: /tmp/cc5Vvv83.o: in function `main':
/home/ivan/first/main.cpp:6: undefined reference to `A<int>::print()'
collect2: error: ld returned 1 exit status
Если я скопирую это определени и перемещу в хэдэр, то программа заработает и выдаст то, что надо:
int
some
some
Но я хотел бы не помещать определение метода A<int>::print() в хэдэр, поэтому в test.h оставляю:
template<>
class A<int>
{
public:
void print();
};
а в test.cpp помещаю:
template<>
void A<int>::print()
{
std::cout << "int" << std::endl;
}
результат:
test.cpp:11:6: error: template-id ‘print<>’ for ‘void A<int>::print()’ does not match any template declaration
11 | void A<int>::print()
| ^~~~~~
In file included from test.cpp:2:
test.h:15:14: note: candidate is: ‘void A<int>::print()’
15 | void print();
| ^~~~~
Вопросы:
1)Как в данном случае оставить определение класса A<int> в test.h, а определение метода A<int>::print() в test.cpp и чтобы программа заработала?
2)Как вообще правильно решать такие ситутуации? Может просто следует оставлять определение в хэдэре и не париться(правда, насколько я знаю, таким образом мы увеличим время компиляции)?
Ответы (1 шт):
Три момента:
- о том, что шаблон явно инстанцируется, и его определение будет доступно в какой-то единице трансляции, следует объявлять в заголовочном файле. Причем для полной специализации
A<int>этого делать не надо:
extern template class A<double>;
extern template class A<char>;
- определение специализации должно быть в заголовочном файле и видно всем пользователям
- определение функции полностью специализированного класса в .cpp выглядит вот так
void A<int>::print()
{
std::cout << "int" << std::endl;
}