tly
tly

Reputation: 1262

Specialization of template class with pointer template argument

I would like to specialize a template class for several pointers to different objects. This works as expected for normal pointers:

struct Base{} b;

template<Base* B> struct Test{};

template<> struct Test<&b>{};

But not for pointers to Derived objects:

struct Derived : Base{} d;

template<> struct Test<&d>{};

the coliru compiler (i think its gcc 5.2) shows the following error:

main.cpp:14:26: error: could not convert template argument '& d' to 'Base*'
 template<> struct Test<&d>{};

I dont know, why this is not allowed and would like to know if there is any workaround for the problem...

Here is a link to the code in coliru.

Upvotes: 2

Views: 230

Answers (2)

Christophe
Christophe

Reputation: 73366

You could define the generic template for all types (if relevant) and a partial specialisation for pointer types:

template <typename T>  
struct MyTest {   // generic implementation for all types 
    MyTest() {    // here I make it unrelevant
        static_assert(is_pointer<T>::value , "this class must be used with a pointer");
    }
};

template <typename T>
struct MyTest<T*> { // partial specialisation for pointer types
    MyTest() {
        cout <<"generic implementation"<<endl;
    }
};

You can define more specialisations as needed:

struct Base {}; 
struct Derived : Base {};

template <>
struct MyTest<Base*> {  // specialisation for Base
    MyTest() {
        cout <<"specialized implementation for Base"<<endl;
    }
};

template <>
struct MyTest<Derived*> {  // specialisation for Derived
    MyTest() {
        cout <<"specialized implementation for Derived"<<endl;
    }
};

And here how you can use it:

MyTest<Base> mt1;   //<== faills because Base is not a poiner
MyTest<int*> mt0;   // generic template
MyTest<Base*> mt2;  // Base specialisation 
MyTest<Derived*> mt3; // derived specialisation 

Here an online demo.

Upvotes: 0

bolov
bolov

Reputation: 75678

It is possible if you are willing to change the template parameters a bit:

struct Base {} b;
struct Derived : Base {} d;
struct A {} a;

template <class T, T *B,
          class = std::enable_if_t<std::is_base_of<Base, T>::value>>
struct Test {};

template <> struct Test<Base, &b> {};     // OK
template <> struct Test<Derived, &d> {};  // OK

template <> struct Test<A, &a> {};        // compile error

Upvotes: 2

Related Questions