LINUX.ORG.RU

История изменений

Исправление 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&); }
Foo.cpp
#include <iostream>

template <typename T>
void Foo::print(const T &value) { std::cout << value << '\n'; }

template class Foo<int>;
template class Foo<float>;
main.cpp
#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&); }
Foo.cpp
#include <iostream>

template <typename T>
void Foo::print(const T &value) { std::cout << value << '\n'; }

template class Foo<int>;
template class Foo<float>;
main.cpp
#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');
}