2015-12-30 4 views
2

Я хотел бы специализировать класс шаблона для нескольких указателей для разных объектов. Это работает, как ожидается, для обычных указателей:Специализация класса шаблона с аргументом шаблона указателя

struct Base{} b; 

template<Base* B> struct Test{}; 

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

Но не для указателей на Derived объектов:

struct Derived : Base{} d; 

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

coliru компилятор (я думаю, что его gcc 5.2) показывает следующее сообщение об ошибке:

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

Я не знаю, почему это не разрешено и хотелось бы знать, есть ли какие-либо способы решения проблемы ...

Here является ссылкой на код в coliru.

+1

Нет. Даже непринужденные правила для шаблонов, не связанных с типом аргументов в C++ 17, до сих пор не позволяют указателям на подобъекты. –

ответ

2

Это возможно, если вы готовы изменить шаблон параметров немного:

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 
+0

Я думаю, что это лучшая альтернатива, спасибо. – tly

0

Вы можете определить общий шаблон для всех типов (при необходимости) и частичную специализацию для типов указателей:

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

Вы можете задать дополнительные специализации по мере необходимости:

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

И ч как вы можете его использовать:

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 

Здесь online demo.

+1

параметр шаблона в его примере является параметром шаблона непигового типа – bolov

Смежные вопросы