开发者

Partial template specialization - member specialization

Say I have this开发者_Python百科 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?


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.


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


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*/}


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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜