Getting "illegal use of explicit template arguments" when doing a pointer partial specialization for a class method

Kunashu picture Kunashu · Apr 22, 2013 · Viewed 13.3k times · Source

Hello I'm having problems with partial specialization. What I want to do is have a class that has a template member function that will interpret a given value to one specified by the user. For instance the class name is Value and here is a snippet of what I want to do:

int *ptr1 = new int;
*ptr1 = 10;
Value val1 = ptr1;
int *ptr2 = val1.getValue<int*>();

Value val2 = 1;
int testVal = val2.getValue<int>();

Here is how I implemented such class:

struct Value {

    Value(void *p) : val1(p){}
    Value(int i) : val2(i){}

    template<typename T>
    T getValue();

    void *val1;
    int val2;
};

template<typename T>
T*  Value::getValue<T*>() {
    return reinterpret_cast<T*>(val1);
}

template<>
int Value::getValue<int>() {
    return val2;
}

When I compile I'm getting the following error:

error C2768: 'Value::getValue' : illegal use of explicit template arguments

Basically its complaining about the pointer template part of the code:

template<typename T>
T* Value::getValue<T*>() {
    return reinterpret_cast<T*>(val1);
}

I know this problem can be implemented with a simple union, But this code is a stripped down version of a bigger code.

Does someone know what the problem could be? What I would like to do is separate one code for when using pointers and other for when not using pointers . I'm really stuck and I always investigate instead of asking, but I haven't found any good info about it.

Answer

Function templates cannot be partially specialised, but most of the time, you can use the delegate-to-class trick. In you example it would be like this:

struct Value {
  template<typename T>
  T getValue() {
    return Impl_getValue<T>::call(*this);
  }
};

template <typename T>
struct Impl_getValue
{
  static T call(Value &v) {
    //primary template implementation
  }
};

template <typename T>
struct Impl_getValue<T*>
{
  static T* call(Value &v) {
    return reinterpret_cast<T*>(v.val1);
  }
};