Задать вопрос
@originalnii

Можно ли объявить и реализовать шаблонный метод класса в исходном файле в C++?

В программе, которую я пишу для курса, мне понадобилось описать класс с шаблонным методом в отдельном файле. Так как у шаблонов проблемы с разбиением по заголовочным и исходным файлам, написал в заголовочном так:

class Database {
public:
	template <class F>
	int RemoveIf(F predicate) {
		/*
		...
		*/
	}
};

В соответствующем .cpp файле про этот метод ничего нет. Но. В файлах, приложенных к этой задаче составителями курса, были шаблонные функции (не методы класса), объявленные и реализованные целиком в исходном, .cpp файле. Так что чистого перфекционизма вопрос: можно ли так же целиком поместить в .cpp файл определение и реализацию шаблонного метода класса? И если да, то как?
  • Вопрос задан
  • 2341 просмотр
Подписаться 1 Простой 1 комментарий
Решения вопроса 2
gbg
@gbg Куратор тега C++
Любые ответы на любые вопросы
В *.cpp можно поместить определение шаблона целиком. Строго говоря, у шаблона нет реализации - она появляется в тот момент, когда шаблон конкретизируется.

При этом важно понимать, что в таком случае, вы нигде кроме этого *.cpp шаблоном воспользоваться не сможете - получите ругань линковщика на повторы.

Именно из первого и второго следует, что место шаблонам - целиком в .h или .hpp (что более правильно). А методичка, где шаблон запихали в *.cpp имеет низкое качество и годится для растопки печки-буржуйки.
Ответ написан
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Нет, все методы класса надо объявить в хедере (тем более публичные): иначе как пользователи класса смогут к нему обращаться? С простыми функциями так можно, если они не используются где-то извне. Или с классном можно, только если он весь целиком объявлен в cpp файле и, соответственно, его нельзя использовать вне этого файла.

Можно еще перенести в cpp файл определение шаблонных классов/методов/функций, но для этого надо в хедере указать через forward declaration все используемые специализации шаблона. Например так:
template <>
int Database::RemoveIf<bool>(bool predicate);


Конечно, там должен быть не bool а тип вашего предиката. И надо такие штуки воткнуть в хедер для ВСЕХ типов, которые в других файлах пихаются в шаблон.

Обычно нужно определять функцию прямо в хедере, потому что когда компилятор собирает cpp файл с определением класса, он не видит, как этот шаблон используется в других файлах, поэтому он не может догадаться сгенерировать код для используемых специализаций шаблона. Если же реализовывать функцию в хедере, то реализация будет в том же файле, что и ее использование. Поэтому компилятор сможет выбрать нужные типы. Forward declaration позволяет обойти эту проблему.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы