3

this might be question that someone asked before but i can't find it...

i have a class in a .hpp file :

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
}

The template method should work for int, double... but not for string. Thus in my .hpp file, I defined what func does for numbers and in my .cpp file I wrote :

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

But when I use the function func with std::string, the program calls the methods for numbers... So I replaced the .hpp file by :

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
}

and my .cpp file became :

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

and then everything works !

my question is, is this the correct way to do that ?

PinkFloyd
  • 2,103
  • 4
  • 28
  • 47

2 Answers2

3

That's not a partial specialization (there are no template parameters left un-specialized) it's an explicit specialization.

Templates must be visible to the code that uses them, if you don't declare the specialization in the header file then code that tries to call A::func with a string will instantiate the primary template (the one for numbers) and use that, because they don't know the `string specialization even exists.

So you must (at least) declare the specialization in the header in order for it to be usable outsde the .cpp file:

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

However your alternative using an overload is simpler and is perfectly acceptable. It works because the overload for string is declared in the header, so code that calls it knows which function to call.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • if i understood correctly, the header has to contain `template<> void func(std::string s){//to something}` or `void func(std::string s){//do something}` ? – PinkFloyd Jul 09 '13 at 11:51
  • No, you didn't understand correctly. Those are definitions. The header only has to contain declarations, not definitions (it can also contain definitions if they are marked `inline`) – Jonathan Wakely Jul 09 '13 at 12:03
  • but for templates, the definitions are in the header file... right ?! – PinkFloyd Jul 09 '13 at 12:05
  • and the header files can contain definitions if they are directly given, i mean inside the class definition... right?! – PinkFloyd Jul 09 '13 at 12:07
  • 1
    For class templates and non-specialized function templates and inline functions the definitions must be in the header file. Member function definitions in the class definition are implicitly inline. – Jonathan Wakely Jul 09 '13 at 12:32
0

Overloading is a good approach for many purposes. However, I suspect your original template approach could be made to work too if you add a specialization for const char * as well. That way, you could pass in string literals without it resolving to the numbers version.

Peter Bloomfield
  • 5,578
  • 26
  • 37
  • no sure i understood what you mean... what is "resolving to the numbers version" ? – PinkFloyd Jul 09 '13 at 11:57
  • In the original question, you indicated that the method for numbers was being called instead of the one specialized for strings. I could be wrong, but my guess is that you were passing in a string literal? String literals resolve to `const char *`, which is a numeric type, which is why it was calling the numbers method, not the string one. – Peter Bloomfield Jul 09 '13 at 12:12
  • like this : `func("blalba")` ? no i passed a string like this `std::string s("blabla"); func(s)`. – PinkFloyd Jul 09 '13 at 12:12
  • Oh I see. My mistake. I see the problem was resolved in the other answer anyway. :) – Peter Bloomfield Jul 09 '13 at 12:47