template <class T>
class Test
{
public:
template<class U> void f(); //generic function
template<> void f<char>(); //Specialization for char.
};
template <class T>
template<class U>
void Test<T>::f() //Definition of generic function
{
}
template<>
template<> void Test<char>::f<char>(){} //Definition of specialization.
int main()
{
Test<char> ob1;
ob1.f<char>(); //Works fine.
Test<int> ob2;
ob2.f<char>(); //Produces linker error.
}
Linker error is
error LNK2019: unresolved external symbol "public: void __thiscall
Test<int>::f<char>(void)"
My requirement is: I should be able to pass any type to Test class and any type to function f(). I should be able to use all combinations of types like below.
Test f() -------------- int char char int int int
I can solve the error by defining another function like below.
template<>
template<> void Test<int>::f<char>(){}
But then what is the use of making Test class as Template ? How to make it work for all combinations ?
C++03, §14.7.3/2:
An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member. An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member.
Therefore you should declare your specialization outside of a class, for example:
template <class T>
class Test
{
public:
template<class U> void f(); //generic function
};
template <class T>
template <class U>
void Test<T>::f() {} //Definition of generic function
template<>
template<>
void Test<char>::f<char>(){} //Specialization.
int main()
{
Test<char> ob1;
ob1.f<char>();
Test<int> ob2;
ob2.f<char>();
}
The problem that you are facing is that you have declared the specialization of f for char in the Test template, and that is incorrect. The compiler is not detecting the error, but it is getting confused and interpreting that you want to provide the specialization of f for char in all template instantiations:
template <typename T>
struct Test {
template <typename U> void f();
template <> void f<char>(); // <- Incorrect
};
When you write Test<int> the compiler instantiates the template and is (mistakenly) accepting it and interepreting that there is an specialization of f for char in Test<int>.
Just remove the line, and you will get the code to compile. It will use the specialization only for Test<char>::f<char>(), and I am not sure whether that is what you want.
If your intention is specializing f for char with all instantiating types, that is not allowed. When you define a template specialization, all enclosing templates be specialized. A common work around is not providing an specialization but a different overload of the member function:
template <typename T>
struct Test {
template <typename U> void f( U );
void f( char );
};
But that won't help you much there, as you cannot provide different overloads for the same arguments (in your case no arguments). Also, in your case you must explicitly call the template to differentiate, and code that explicitly requests the template would not pick up the overload:
int main() {
Test<int> t;
t.f<char>(); // will call template, not "void f(char)"!!
}
Without more details on what you really want to achieve I cannot think on other potential solution to the issue.
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