Reputation: 5462
Say I have this template class:
template<typename T> class MyClass{
public:
MyClass(const T& t):_t(t){}
~MyClass(){}
void print(){ cout << _t << endl; }
private:
T _t;
};
And I want to specialize it, so similarly I define:
template<> class MyClass<double>{
public:
MyClass(const double& t):_t(t){}
~MyClass(){}
void print(){ cout << _t << endl; }
private:
double _t;
};
Now, this is ok as long as we're talking about small classes. If I have a very long class, it would be a lot smarter to specialize print()
alone. I know how to do it with non-member function. Is there any way to do it with member functions?
Upvotes: 2
Views: 667
Reputation: 21
in class.h
// declaration of template class
template<typename T>
class MyClass
{
public:
MyClass(T t&):_t(t){}
~MyClass(){}
void print(); // general "declaration".
// don't use inline definition for these case
private:
T _t;
};
// specialization "declaration" of wanted member function
template<>
void MyClass<double>::print();
#include "class.inl" // implementation of template class
in class.inl
// general "definition" of wanted member function
template<typename T>
void MyClass<T>::print()
{
cout << _t << endl;
}
in class.cpp
#include "class.h"
// specialization "definition" of wanted member function
// specialization definition of anyone must be here.. not inl file..
void MyClass<double>::print()
{
cout << "double specialization " << _t << endl;
}
Upvotes: 2
Reputation: 6901
You can specialize your print member function specially for double:
template< typename T >
class MyClass{
public:
MyClass(T t&):_t(t){}
~MyClass(){}
void print(){}
private:
T _t;
};
template< typename T >
void MyClass< T >::print(){/* your specific implementation*/}
template<>
void MyClass< double >::print(){/* your specific implementation*/}
Upvotes: 2
Reputation: 361792
One straightforward solution is, define base class template containing things which you want to specialize, and then specialize this class template instead (it would be a small class, after all):
template<typename T>
struct printable
{
protected:
void print(const T & _t) { }
};
template<>
struct printable<double>
{
protected:
void print(const double & _t) { }
};
And then derived from it:
template<typename T>
class MyClass : public printable<T>
{
typedef printable<T> base;
public:
MyClass(T t&):_t(t){}
~MyClass(){}
void print(){ base::print(_t); } //forward
private:
T _t;
};
You don't need to specialize this class template anymore; make it as huge as you want (and reasonable).
Another alternative is policy-based design in which you pass policy-class(es) as template argument(s) to your class template (called host class).
For example,
//lets define few policy classes
struct cout_print_policy
{
template<typename T>
static void print(T const & data)
{
std::cout << "printing using cout = " << data << std::endl;
}
};
struct printf_print_policy
{
static void print(int data)
{
std::printf("printing int using printf = %d\n", data);
}
static void print(double data)
{
std::printf("printing double using printf = %f\n", data);
}
};
//now define the class template (called host class) that
//accepts policy as template argument
template<typename T, typename TPrintPolicy>
class host
{
typedef TPrintPolicy print_policy;
T data;
public:
host(T const & d) : data(d) {}
void print()
{
print_policy::print(data);
}
};
Test code:
int main()
{
host<int, cout_print_policy> ic(100);
host<double, cout_print_policy> dc(100.0);
host<int, printf_print_policy> ip(100);
host<double, printf_print_policy> dp(100.0);
ic.print();
dc.print();
ip.print();
dp.print();
}
Output:
printing using cout = 100
printing using cout = 100
printing int using printf = 100
printing double using printf = 100.000000
Online demo : http://ideone.com/r4Zk4
Upvotes: 4
Reputation: 64308
In your example, you are using full specialization. In that case, you can do it like this:
template <>
void MyClass<double>::print()
{
cout << _t << endl;
}
but it doesn't work for partial specialization.
Upvotes: 4