Reputation: 5497
I'm trying to specialize a template method of non-template class in its subclass:
// .h file
class MyWriter {
public:
template<typename T>
void test(const T & val) {
std::cout << val << "\n";
}
};
// .cpp file
class MyType {
public:
MyType(int aa, double dd) : a(aa), d(dd) {}
int a;
double d;
};
class MyWriterExt : public MyWriter {
public:
template<> void test(const MyType &val) {
test(val.a);
test(val.d);
}
};
int main() {
MyWriterExt w;
w.test(10);
w.test(9.999);
w.test(MyType(15, 0.25));
return 0;
}
But I receive an error:
Error 1 **error C2912**: explicit specialization;
'void MyWriterExt::test(const MyType &)' is not a specialization of a function
template \testtemplate.cpp 30
How do I extend MyWriter class to support user defined classes?
Upvotes: 7
Views: 2376
Reputation: 55745
Specialization should be done for the same class not for a subclass and also outside of the class body:
class MyWriter {
public:
template<typename T>
void test(const T & val) {
std::cout << val << "\n";
}
};
template<>
void MyWriter::test<MyType>(const MyType & val) {
test(val.a);
test(val.d);
}
You don't need a subclass to specialize the original member function template.
Also consider overloading instead of specialization.
Upvotes: 7
Reputation: 83404
Error 1 **error C2912**: explicit specialization;
'void MyWriterExt::test(const MyType &)' is not a specialization of
a function template \testtemplate.cpp 30
If you want a "specialization" of the templated function in the derived class, the solution is to (in the derived class):
Which gives:
class MyWriterExt : public MyWriter {
public:
/*
template<> void test(const MyType &val) {
test(val.a);
test(val.d);
}
*/
using MyWriter::test ;
void test(const MyType &val) {
test(val.a);
test(val.d);
}
};
How do I extend MyWriter class to support user defined classes?
Now, if you are using MyWriter as an extensible output stream, I'm not sure inheritance is the solution. As already answered by vitaut on his answer; you should specialize your templated function for (and outside) the base object.
How do I extend MyWriter class to support user defined classes?
A better solution would be to follow the C++ stream's convention, that is, using non-friend, non-member functions. In your case, it would be something like:
class MyWriter {
public:
};
template<typename T>
MyWriter & operator << (MyWriter & writer, const T & val) {
std::cout << val << "\n";
return writer ;
}
Anyone could then "specialize" your output function without needing inheritance:
MyWriter & operator << (MyWriter & writer, const MyType & val) {
writer << val.a << val.d ;
return writer ;
}
Which could be written in your main as:
int main() {
MyWriter w;
w << 10 << 9.999 << MyType(15, 0.25);
return 0;
}
Which is, IMHO, quite clearer than an accumulation of function calls (as long as you're not doing formatting, the C++ output streams are SO easy to use).
(of course, I assume MyWriter will do more than a simple redirection to std::cout
. If not, MyWriter is useless...)
Upvotes: 5