specialization of a template method
Hello,
I'd like to specialize a method in a template class for another generic template class and can't figure out how to do it exactly.
The simplified code looks like this:
Code:
template<typename T>
class ClassA
{
public:
ClassA(){...}
~ClassA(void){...}
ClassA(const ClassA<T> &other){...}
ClassA<T>& operator=(const ClassA<T> &other){...}
inline T& operator() (int height, int width){
if (height < 0 || height >= getHeight() || width < 0 || width >= getWidth())
...
else
return _pMat[height][width];
}
inline T operator() (int height, int width) const{
if (height < 0 || height >= getHeight() || width < 0 || width >= getWidth())
...
else
return _pMat[height][width];
}
inline int getWidth(void){return _iWidth;}
inline int getWidth(void) const{return _iWidth;}
inline int getHeight(void){return _iHeight;}
inline int getHeight(void) const{return _iHeight;}
void print(void){
std::cout << "print general" << std::endl;
}
private:
int _iWidth;
int _iHeight;
T** _pMat;
};
template<>
void ClassA< ClassB<int> >::print(void){
std::cout << "print specialized <int>" << std::endl;
}
template <typename U>
class ClassB
{
public:
inline ClassB(){...}
inline ~ClassB(void){...}
inline ClassB(const ClassB<U> &other){...}
inline ClassB<U>& operator=(const ClassB<U> &other){...}
inline U& operator() (int dimension){
if (dimension >= 0 && dimension < getDimension())
return _pData[dimension];
else
...
}
inline U operator() (int dimension) const{
if (dimension >= 0 && dimension < getDimension())
return _pData[dimension];
else
...
}
inline int getDimension(void) const{return _iDimension;}
inline int getDimension(void){return _iDimension;}
inline void print(void){...}
private:
int _iDimension;
U *_pData;
};
if I instantiate the templates like this:
Code:
ClassA< ClassB<int> > test;
test.print();
everything works as desired and the specialized print method is called when ClassB is of type <int>.
but I also need specialized methods for:
Code:
ClassA< ClassB<double> > test1;
ClassA< ClassB<float> > test2;
//etc...
so I'd like to spezialize my print method like this:
Code:
template<>
void ClassA< ClassB<U> >::print(void){
std::cout << "print specialized <U>" << std::endl;
}
I hope this is possible, and I think I'm missing some template syntax to make it work.
I hope someone knows how to do it...
thanks in advance
darksaga
Re: specialization of a template method
AFAIK it's not possible. ClassA< ClassB<U> > is treated as completely different template, because ClassB<U> isn't fully specialized type.
Let's see this in an example:
Code:
#include<iostream>
using namespace std;
template <typename T>
struct A {
void func1() { cout << "general" << std::endl; }
void func2() { cout << "hello" << std::endl; }
};
template <typename T>
struct B {};
// template <> // this line isn't necessary and helpful at all
template <typename U>
struct A< B<U> > {
void func1() { cout << "specialized" << std::endl; }
};
int main() {
A< B<int> > a;
a.func1();
// a.func2(); // uncommented produces error: 'struct A<B<int> >' has no member named 'func2'
return 0;
}
What you can do?
- Copy&paste code from ClassA to ClassA< B<T> > and change T to B<T> in it - maintainability will suffer from it.
- Redesign your code to avoid "tricky" partial specialization.
Re: specialization of a template method
is there any "empirical knowledge" how much the maintainability will suffer, doing it the way you suggested???
my approach is to use:
ClassA< int > var1; ClassA< float > var2; etc...
for 1. dimensional data inside a grid, and
ClassA< ClassB<int> > var1; ClassA< ClassB<float> > var2; etc...
for x. dimensional data inside a grid.
templating both, the grid & the data inside would make my code very generic & thats exacly what I want to achieve.
regards
Re: specialization of a template method
I said that maintainability will suffer, because if you have two (or even more) almost copies of the same code, you are obliged to (properly) propagate changes and that can be simply a source of troubles in future.
There is a not-really-elegant way to achieve code duplication without using copy&paste by hand. You have to get unchangeable code between "specializations" from your class and put it in separate file. Now you can include it in your "specialized" templates. To deal with B<T>, use typedef. Below the idea is shown.
template.cpp
Code:
#include<iostream>
using namespace std;
template <typename T>
class A {
#include "template_.cpp"
public:
void func1() { cout << "general" << std::endl; }
};
template <typename T>
class B {};
template <typename U>
class A< B<U> > {
typedef B<U> T;
#include "template_.cpp"
public:
void func1() { cout << "specialized" << std::endl; }
};
int main() {
A< B<int> > a;
a.func1();
a.func2();
a.func3();
return 0;
}
template_.cpp
Code:
public:
void func2() { cout << "hello" << std::endl; }
T* func3() { return t_; }
private:
T* t_;