Andrew Redd
Andrew Redd

Reputation: 4692

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.

Upvotes: 4

Views: 2607

Answers (4)

Diego Sevilla
Diego Sevilla

Reputation: 29001

You can add vector<ar_index> reflected<bool>::which() to reflected<bool> (and only to it, not to the general template). If you get an error, maybe you're not doing the template specialization correctly...

Upvotes: 0

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 506837

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.

Upvotes: 12

John Dibling
John Dibling

Reputation: 101446

Can't be done directly the way you want. But you can achieve a similar result by not defining reflected() for any class except the specialized one. Then you will get a liner error if you try to use it on a non-supported class.

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

Upvotes: 1

James McNellis
James McNellis

Reputation: 354979

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>&);

Upvotes: 5

Related Questions