История изменений
Исправление KennyMinigun, (текущая версия) :
Да скажите , хоть где это писать:template class Foo<int>;
template class Foo<int>;
Это просто обьявление класса. В данном случае специализации шаблонного класса. И это самое обьявление заставляет компилятор сгенерировать код для класса Foo со значением шаблонного параметра T = int.
«Сгенерировать код» означает, что компилятор в обьектном файле, который получится из файла .cpp, разместит символы к которым потом линкер сможет подлинковать (связать) обращения к такому шаблонному класу с параметром T = int.
Т.е. например Foo.h:
template <typename T>
struct Foo { void print(const T&); }
#include <iostream>
template <typename T>
void Foo::print(const T &value) { std::cout << value << '\n'; }
template class Foo<int>;
template class Foo<float>;
#include "Foo.h"
int main() {
// OK: линкер нашел символ Foo<int>::print(const int&) в Foo.cpp
Foo<int>().print(42);
// OK: линкер нашел символ Foo<float>::print(const float&) в Foo.cpp
Foo<float>().print(3.14f);
// FAIL: линкер не нашел символа Foo<char>::print(const char&)
// error: unresolved reference ...
Foo<char>().print('a');
}
Исходная версия KennyMinigun, :
Да скажите , хоть где это писать:template class Foo<int>;
template class Foo<int>;
Это просто обьявление класса. В данном случае специализации шаблонного класса. И это самое обьявление заставляет компилятор сгенерировать код для класса Foo со значением шаблонного параметра T = int.
«Сгенерировать код» означает, что компилятор в обьектном файле, который получится из файла .cpp, разместит символы к которым потом линкер сможет подлинковать (связать) обращения к такому шаблонному класу с параметром T = int.
Т.е. например Foo.h:
template <typename T>
struct Foo { void print(const T&); }
#include <iostream>
template <typename T>
void Foo::print(const T &value) { std::cout << value << '\n'; }
template class Foo<int>;
template class Foo<float>;
#include "Foo.h"
int main() {
// OK: линкер нашел символ Foo<int>::print(const int&) в Foo.cpp
Foo<int>().print(42);
// OK: линкер нашел символ Foo<float>::print(const float&) в Foo.cpp
Foo<float>().print(3.14f);
// FAIL: линкер не нашел символа Foo<char>::print
// error: unresolved reference ...
Foo<char>().print('a');
}