Частичная специализация шаблона - специализация члена - PullRequest
2 голосов
/ 24 сентября 2011

Скажите, у меня есть шаблон этого класса:

template<typename T> class MyClass{
public:
    MyClass(const T& t):_t(t){}
    ~MyClass(){}
    void print(){ cout << _t << endl; }
private:
    T _t;
};

И я хочу специализировать его, поэтому я так же определяю:

template<> class MyClass<double>{
    public:
        MyClass(const double& t):_t(t){}
        ~MyClass(){}
        void print(){ cout << _t << endl; }
    private:
        double _t;
};

Теперь, это нормально, пока мы говорим о маленьких классах. Если бы у меня был очень длинный класс, было бы намного умнее специализироваться print() в одиночку. Я знаю, как это сделать с помощью функции, не являющейся членом. Есть ли способ сделать это с помощью функций-членов?

Ответы [ 4 ]

4 голосов
/ 24 сентября 2011

В вашем примере вы используете полную специализацию.В этом случае вы можете сделать это так:

template <>
void MyClass<double>::print()
{
  cout << _t << endl;
}

, но это не сработает для частичной специализации.

4 голосов
/ 24 сентября 2011

Одно простое решение - определить base шаблон класса, содержащий вещи, которые вы хотите специализировать, а затем вместо этого специализировать этот шаблон класса (в конце концов, это будет небольшой класс):

template<typename T> 
struct printable
{
 protected:
   void print(const T & _t)  { }
};

template<> 
struct printable<double>
{
 protected:
   void print(const double & _t)  { }
};

А потом на его основе:

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

Вам больше не нужно специализировать этот шаблон класса;сделайте его настолько большим, насколько вы хотите (и разумным).


Другой альтернативой является дизайн на основе политики , в котором вы передаете класс (ы) политики в качестве аргумента (ов) шаблонав шаблон вашего класса (называется host class).

Например,

//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);
    }
};

Тестовый код:

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();
}

Выход:

printing using cout = 100
printing using cout = 100
printing int using printf = 100
printing double using printf = 100.000000

Онлайн демо: http://ideone.com/r4Zk4

2 голосов
/ 24 сентября 2011

Вы можете специализировать свою функцию члена печати специально для двойного:

template&lt typename T &gt class MyClass{ public: MyClass(T t&):_t(t){} ~MyClass(){} void print(){} private: T _t; }; template&lt typename T &gt void MyClass&lt T &gt::print(){/* your specific implementation*/} template&lt&gt void MyClass&lt double &gt::print(){/* your specific implementation*/}

1 голос
/ 03 января 2013

в классе.ч

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

в классе .inl

// general "definition" of wanted member function
template<typename T>
void MyClass<T>::print()
{
    cout << _t << endl;
}

в 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...