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;
}
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.
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.
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.
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.
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With