2013-07-10 4 views
1

Я видел интересную вещь, но не мог понять, почему.Множество определений функции в шаблонных классах

template<class dataType> 
Class A 
{ 
AFnc(); 
} 

template<> A<int>::AFnc() { } 

Использование только специализированного шаблона создает ошибку, указывающую на множественное определение той же функции. И он говорит, что он был создан на том же месте. Но если добавить

template<class dataType> 
A<dataType>::AFnc() 
{ 
} 

Тогда он избавляется от ошибок.

Почему? Не мог бы кто-нибудь объяснить это поведение.

+1

Вам нужно очистить свой синтаксис.Код в это время настолько «грязный», что нет способа убедиться, что это реально или нет. Где тип возврата для функции? – AnT

ответ

3

(Вы должны очистить свой синтаксис. Я предполагаю, что фактический код не все эти синтаксические ошибки.)

Явная специализация функции шаблона больше не шаблон, так как он не зависит от какой-либо параметры шаблона. С точки зрения Единого правила определения (ODR) это «обычная» функция. И как «обычная» функция, она должна быть объявлена ​​ в заголовочном файле, а определен только один раз в некотором файле реализации. По-видимому, вы определили свою специализацию в файле заголовка, что приводит к нарушению ODR, если заголовочный файл включен в несколько единиц перевода (например, ошибки «множественного определения»).

В вашем примере template<> void A<int>::AFnc() (я добавил void в качестве типа возврата) больше не является шаблоном. Это означает, что это определение

template<> void A<int>::AFnc() { } 

должны быть перемещены из заголовочного файла в какой-то файл реализации. Между тем, в заголовочном файле вы должны держать, не определяющую декларацию для этой функции

template<> void A<int>::AFnc(); // <- note, no function body 

, чтобы позволить компилятору знать, что такая специализация существует.

В общем, помните о простом правиле: если ваш шаблон функции все еще зависит от некоторых параметров неопределенного шаблона, он является истинным шаблоном, и он должен быть определен в заголовочном файле. Но как только вы «исправите» все параметры (по явной специализации), это уже не шаблон. Он становится обычной функцией, которая должна быть объявлена ​​ в заголовочном файле, а определен только один раз в некотором файле реализации.

P.S. Вышеупомянутое относится к не-встроенным функциям. Встроенные функции могут быть (и, как правило, предполагается) определены в файлах заголовков.

P.P.S. Такая же логика применяется к явным специализациям статических элементов данных классов шаблонов.

+0

... или объявить его 'inline' –

+0

Я хотел уметь дать +5 для этого ответа, поэтому очень хорошо объяснил. – Werner

1

Думаю, вы помещаете явное инстанцирование в файл заголовка. Затем его код испускается в каждой единицы перевода, которая включает этот файл. Просто перетащите код

template<> A<int>::AFnc() { } 

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

+0

«Просто двигаться» недостаточно. В файле заголовка должен быть оставлен не определяющий объявление 'template <> A :: AFnc();'. – AnT

Смежные вопросы