Специализация шаблонной функции-члена только для одного типа - PullRequest
4 голосов
/ 12 ноября 2010

У меня есть шаблонный класс, который имеет много функций, но по сути является векторным классом. Я хочу добавить одну функцию только к типу bool.

#include <vector>
template <typename T>
class reflected{
    private:
        T*dev_;
        T*host_;
        ar_size size;
        reflected<T>& operator=(reflected<T>& rhs);//do not impliment.  assign not allowed.
        reflected( reflected<T>& old);  //do not impliment. Copy not allowed.
    public:
        reflected():size(0L),dev_(NULL),host_(NULL){}
        reflected(ar_size n):size(n),dev_(NULL),host_(NULL){init();}
        reflected(const T*x,ar_size n):size(n),dev_(NULL),host_(NULL){init();set(x);}
        ~reflected();
        void init();
        void init(ar_size n);
        void init(const T*x,ar_size n);
        void set(const T * x);
        void setat(ar_index i, T x);
        const T getat(ar_size i);
        const T * devPtr();
        const T operator [](const ar_index i);
        ar_size length(){return size;}
};

Я хочу добавить функцию vector<ar_index> reflected<bool>::which() в особый случай отраженного класса, который является единственным случаем, когда это имеет смысл. Каков наилучший способ сделать это. компилятору, похоже, не нравится добавлять which () к отраженному и определять его только для bool.

Ответы [ 4 ]

12 голосов
/ 12 ноября 2010

Вы можете определить его в шаблоне класса следующим образом

template <typename T> struct id { typedef T type; };

template <typename T>
class reflected{
    private:
        /* ... */
        vector<ar_index> which(id<bool>) { 
          /* ... */
        }
    public:
        /* ... */
        vector<ar_index> which() { return which(id<T>()); }
};

Это дает ошибку времени компиляции, если вы вызываете which на reflected<T>, для которого T вы не дали правильное определение.

4 голосов
/ 12 ноября 2010

Если вы хотите добавить только один вопрос, вы можете объединить наследование со специализацией:

template <typename T>
class reflected_base { 
    // your current 'reflected' contents go here
}; 

template <typename T>
class reflected : public reflected_base { };

template <>
class reflected<bool> : public reflected_base {
    vector<ar_index> which();
};

Недостатком этого подхода является то, что вам приходится переопределять определенные операции (деструкторы, конструкторы копирования и т. Д.) Для каждой специализации. Другой вариант будет:

template <typename T>
class specialized_reflected { };

template <>
class specialized_reflected<bool> {
public:
    vector<ar_index> which();
};

template <typename T>
class reflected : public specialized_reflected<T> {
    // your current 'reflected' contents go here
};

Хотя, тогда есть потенциальные проблемы с зависимым поиском имени. Третий вариант (и, вероятно, тот, который я выбрал бы) состоял бы в использовании функции, не являющейся членом:

vector<ar_index> which(reflected<bool>&);
1 голос
/ 12 ноября 2010

Не может быть сделано прямо так, как вы хотите.Но вы можете достичь аналогичного результата, не определяя reflected() для любого класса, кроме специализированного.Тогда вы получите ошибку лайнера, если попытаетесь использовать ее в неподдерживаемом классе.

#include <string>
#include <sstream>
using namespace std;

template<typename A>
class Gizmo
{
public:
    Gizmo(){};
    int which();    
};

template<> int Gizmo<bool>::which()
{
    return 42;
}

int main()
{

    Gizmo<bool> gb;
    gb.which();

    Gizmo<int> gi;
    gi.which(); // LINKER ERROR for Gizmo<int>which()

    return 0;
}
0 голосов
/ 12 ноября 2010

Вы можете добавить vector<ar_index> reflected<bool>::which() к reflected<bool> (и только к нему, а не к общему шаблону).Если вы получаете сообщение об ошибке, возможно, вы неправильно выполняете специализацию шаблона ...

...