Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specializing a template class member function for only one type

I have a template class that has lots of functions but is essentially a vector class. I want to add one function to just the bool type.

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

I want to add a function vector<ar_index> reflected<bool>::which() to the special case of the reflected class, which is the only case where it would make sense. What is the best way to do this. the compiler seems to not like adding which() to reflected and only defining it for bool.

like image 454
Andrew Redd Avatar asked Dec 03 '22 10:12

Andrew Redd


2 Answers

You can define it in the class template like this

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

This gives a compile time error if you call which on a reflected<T> for whose T you haven't given the proper definition.

like image 76
Johannes Schaub - litb Avatar answered Dec 31 '22 02:12

Johannes Schaub - litb


If you want to add just one question, you can combine inheritance with specialization:

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

The downside of this approach is that you have to reimplement certain operations (destructors, copy constructors, etc.) for each specialization. Another option would be:

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

Though, then there are potential issues with dependent name lookup. A third option (and probably the one I would choose) would be to use a non-member function:

vector<ar_index> which(reflected<bool>&);
like image 34
James McNellis Avatar answered Dec 31 '22 02:12

James McNellis