Создание и использование шаблона файла с перекрестным исходным кодом

У меня есть класс с несколькими функциями-членами шаблона, которые я хотел бы распределить между несколькими исходными файлами, чтобы ускорить время компиляции. (Шаблоны являются деталями реализации и не предназначены для использования вне класса, поэтому их определение находится в источниках, а не в заголовках.)

Как мне разделить эти шаблоны таким образом, чтобы не было ошибок компоновщика? Если у меня есть исходный файл A с использованием шаблона, определенного в исходном файле B, как мне убедиться, что соответствующий экземпляр шаблона создан компилятором?


person fbrereto    schedule 31.08.2010    source источник


Ответы (2)


Я не мог ответить на него лучше, чем FAQ по C++:
https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl

person Karel Petranek    schedule 31.08.2010
comment
export практически не реализуется компиляторами и считается устаревшим в C++0x. Его не следует использовать для нового кода. - person Billy ONeal; 31.08.2010
comment
Ах, извините, я имел в виду ссылку на 35.15. Тем не менее, в любом случае полезно прочитать все часто задаваемые вопросы, начиная с 35.13, для лучшего понимания. - person Karel Petranek; 31.08.2010
comment
@Billy: export не устарело в C++0x — оно полностью удаляется. Поскольку его реализовал только один внешний интерфейс компилятора (EDG), и ребята из EDG попросили его удалить, казалось, не было особых причин откладывать его удаление. - person Jerry Coffin; 31.08.2010
comment
@PanwenWang Спасибо, исправлено! - person Karel Petranek; 20.08.2015

Просто не объявляйте эти элементы шаблона как часть класса в заголовочном файле. Затем определите свои шаблоны только в исходном файле. Например:

MyClass.hpp

class MyClass
{
public:
    void SomePublicMethod() const;
};

MyClass.cpp

template<class T>
void SomethingWithT(T myVal)
{
    // ...
}

void MyClass::SomePublicMethod() const
{
    SomethingWithT(42);
}
person Billy ONeal    schedule 31.08.2010
comment
Хороший обходной путь :) Это может выглядеть не так элегантно, поскольку требует перемещения методов-членов (даже если они закрыты) за пределы класса, а затем передачи указателя this. Создание экземпляра шаблона вручную, на мой взгляд, является более чистым подходом. - person Karel Petranek; 31.08.2010
comment
@Billy: Что, если я хочу SomethingWithT в исходном файле A и SomePublicMethod в исходном файле B? (SomethingWithT компилируется долго...) - person fbrereto; 31.08.2010
comment
@dark: за исключением того, что ни один известный компилятор не реализует создание экземпляра шаблона вручную. Да, я согласен, что это было бы чище, но оно основано на ключевом слове export, которое А. реализовано только в EDG, а Б. удалено. - person Billy ONeal; 31.08.2010
comment
@fbereto: Вы не можете этого сделать. Для этого потребуется export, который сталкивается с проблемами, описанными в моем предыдущем комментарии. Шаблоны создаются там, где они используются. - person Billy ONeal; 31.08.2010
comment
Создание экземпляра шаблона вручную (конечно) реализовано во всех компиляторах, поддерживающих шаблоны. Вы читали (обновленную ссылку) FAQ, который я разместил в своем ответе? - person Karel Petranek; 31.08.2010
comment
@dark_charlie: Да, я прочитал ссылку. Да, вы можете заставить компилятор создать экземпляр шаблона в единице перевода. Но вы не можете заставить компилятор не создавать экземпляр шаблона там, где он используется в другой единице перевода. - person Billy ONeal; 31.08.2010
comment
@Billy ONeal: Извините, я не понимаю вашего комментария :( Конечно, после создания экземпляра шаблона его нельзя удалить. - person Karel Petranek; 31.08.2010