tags:

views:

105

answers:

2

Is it possible to do this kind of specialization?
If so, how?

The specialization in question is marked //THIS SPECIALIZATION WILL NOT COMPILE I have used VS2008, VS2010, gcc 4.4.3 and neither can compile this.

I know i can avoid this by overloading func but i want to know if there is a way to do this with template specialization. (impractical/inadvisable though it may be)

#include<iostream>
#include<string>

using namespace std;

template <typename ALPHA>
class klass{
    public:
        template <typename BETA>
        void func(BETA B);
};

template <typename ALPHA> template <typename BETA>
void klass<ALPHA>::func(BETA B){
    cout << "I AM A BETA FUNC: " << B <<endl;
}

//THIS SPECIALIZATION WILL NOT COMPILE
template <typename ALPHA> template <>
void klass<ALPHA>::func(string B){
    cout << "I AM A SPECIAL BETA FUNC: " << B <<endl;
}

int main(){
    klass<string> k;
    k.func(1);
    k.func("hello");
    return 0;
}
+5  A: 

Just make the string version of func a regular non-template member function that overloads with the template version:

#include<iostream>
#include<string>

using namespace std;

template <typename ALPHA>
class klass{
    public:
        template <typename BETA>
        void func(BETA B);
        void func(string b);
};

template <typename ALPHA> template <typename BETA>
void klass<ALPHA>::func(BETA B){
    cout << "I AM A BETA FUNC: " << B <<endl;
}

template <typename ALPHA>
void klass<ALPHA>::func(string B){
    cout << "I AM A SPECIAL BETA FUNC: " << B <<endl;
}

int main(){
    klass<string> k;
    k.func(1);
    k.func("hello");
    return 0;
}

In addition to it compiling, there's another benefit here in that you will get more intuitive behavior. See "Why Not Specialize Function Templates?" from GOTW.

Edit: To directly answer your original question, no this is not a compiler limitation, it is something that is disallowed by the C++ standard.

The C++ Standard, 14.7.3/18 says (in part):

In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.

This means that since klass is a template, you cannot specialize klass::func without also specializing klass.

Tyler McHenry
That does not work, k.func("hello"); will call the template function and not the overloaded function.
LoudNPossiblyRight
Because `"hello"` is a `const char*`, not a `string`. Either add another overload for `const char*`, or call as `k.func(string("hello"))`.
Tyler McHenry
+2  A: 

To answer the question you ask in the title: no, this is not a compiler limitation. This is a language limitation. In C++, in order to explicitly specialize a nested template (be that a class template or a member function template) you have to also explicitly specialize the enclosing template.

You are trying to explicitly specialize the nested template without specializing the enclosing template. This will not compile.

When it comes to member function templates, when template parameter is associated with some function parameter (as in your case), you can often replace explicit specialization with overloading, as suggested in Tyler's answer. In other situations you'd have to use a different workaround.

AndreyT