2013-07-09 4 views
3

это может быть вопрос, что кто-то спросил раньше, но я не могу найти его ...C++ шаблон частичная специализация

У меня есть класс в .hpp файле:

class A{ 
    public: 
     A(){//constructor} 
     ~A(){//destructor} 
     //some public methods and arguments 

     template<typename Type> 
      void func(Type t){//do something for numbers} 

    private: 
     //some private methods and arguments 
} 

Метод шаблон должен работать для int, double ... но не для строки. Таким образом, в моем .hpp файле, я определил, что func делает для чисел и в моем .cpp файле я написал:

template<> 
void A::func(std::string t){ // do something in that case} 

Но когда я использую функцию func с std::string, программа вызывает методы для чисел ... Так что я заменить файл .hpp по:

class A{ 
    public: 
     A(){//constructor} 
     ~A(){//destructor} 
     //some public methods and arguments 

     template<typename Type> 
      void func(Type t){//do something for numbers} 
     void func(std::string s); 

    private: 
     //some private methods and arguments 
} 

и мой .cpp файл стал:

void A::func(std::string t){ // do something in that case} 

а потом все работает!

мой вопрос в том, что это правильный способ сделать это?

+0

Я полагаю, что второй большой блок - это hpp, а не cpp? правда ? – Bruce

+0

Да, я отредактировал эту ошибку ... извините – PinkFloyd

+0

Нет pb, я просто не был уверен, поэтому сам не редактировал. – Bruce

ответ

3

Это не частичная специализация (нет параметров шаблона, оставленных неспециализированными), это явная специализация.

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

Таким образом, вы должны (по крайней мере) объявить специализацию в заголовке для того, чтобы можно было использовать outsde файл .cpp:

template<> 
void A::func(std::string t); 

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

+0

Если я правильно понял, заголовок должен содержать 'template <> void func (std :: string s) {// to something}' или 'void func (std :: string s) {// сделать что-то}'? – PinkFloyd

+0

Нет, вы не поняли правильно. Это определения. Заголовок должен содержать только декларации, а не определения (он также может содержать определения, если они помечены 'inline') –

+0

, но для шаблонов определения находятся в файле заголовка ... правильно?! – PinkFloyd

0

Перегрузка - хороший подход для многих целей. Тем не менее, я подозреваю, что ваш оригинальный подход к шаблону можно было бы заставить работать, если вы добавите специализацию для const char *. Таким образом, вы можете передать строковые литералы, не переходя к версии чисел.

+0

Не уверен, что я понял, что вы имеете в виду ...что такое «разрешение на версию номера»? – PinkFloyd

+0

В исходном вопросе вы указали, что метод чисел вызывается вместо специализированного для строк. Я могу ошибаться, но я предполагаю, что вы проходили строковый литерал? Строковые литералы разрешают 'const char *', который является числовым типом, поэтому он вызывает метод чисел, а не строковый. –

+0

вот так: 'func (" blalba ")'? no я передал строку, подобную этой 'std :: string s (« blabla »); FUNC (ы) '. – PinkFloyd

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