Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template member specialization - is this a compiler limitation?

Tags:

c++

templates

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;
}
like image 620
LoudNPossiblyWrong Avatar asked Jun 10 '10 14:06

LoudNPossiblyWrong


People also ask

Are template specializations inline?

An explicit specialization of a function template is inline only if it is declared with the inline specifier (or defined as deleted), it doesn't matter if the primary template is inline.

What is the main problem with templates C++?

C++ templates can't use normal run-time C++ code in the process of expanding, and suffer for it: for instance, the C++ factorial program is limited in that it produces 32-bit integers rather than arbitrary-length bignums.

What is meant by template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.

How will you restrict the template for a specific datatype?

There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.


2 Answers

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.

like image 186
Tyler McHenry Avatar answered Oct 05 '22 17:10

Tyler McHenry


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.

like image 38
AnT Avatar answered Oct 05 '22 18:10

AnT