Сначала вы должны понять механизм шаблонов. Шаблоны не компилируются, они создаются при использовании, а затем их экземпляр компилируется. Таким образом, компилятор должен иметь полное определение шаблона в каждом модуле, использующем функцию шаблона, чтобы сначала создать их экземпляры в соответствии с переданными вами параметрами.
Для решения вашей проблемы есть три решения, но вы увидите, что оба они приводят к одному и тому же результату. Либо вы реализуете все свои шаблоны в файле заголовка внутри определения класса (мы используем суффикс .hxx вместо .h, чтобы уточнить, что они содержат определения шаблонов):
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T& t) {
t.doSomething();
}
};
#endif
Или вы можете передать определение из класса, но все еще в файле заголовка:
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T&);
};
template <class T>
void Foo::bar(const T& t) {
t.doSomething();
}
#endif
Наконец, вы можете реализовать тела шаблонных методов во внешнем файле (с префиксом .cxx по той же причине). Он будет содержать тела методов, но не будет включать "Foo.hxx". Вместо этого это «Foo.hxx», который будет включать «Foo.cxx» после определения класса. Таким образом, когда компилятор разрешает директиву #include, он находит все определение шаблона в том же модуле, что позволяет ему создать его экземпляр:
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T&);
};
#include "Foo.cxx"
#endif
// Foo.cxx
template <class T>
void Foo::bar(const T& t) {
t.doSomething();
}
Выбор между этими тремя способами реализации шаблонов скорее вопрос читабельности (и вкуса).
Второй и третий эквивалентны с точки зрения сгенерированного кода, но я бы предпочел не использовать решение с файлом cxx, потому что оно часто приводит к тупым ошибкам, когда вы забываете инвертировать include.
Более того, известные библиотеки C ++, такие как STL или Boost, предлагают свой код только в файлах заголовков, что является признаком хорошего дизайна. Используя внешнее определение внутри заголовков, вы уточняете определение своего класса. Вы также запрещаете компилятору автоматически встраивать методы, что, по словам Херба Саттера, http://www.gotw.ca/gotw/033.htm
person
jopasserat
schedule
30.11.2010