2009-11-01 5 views
1

Я хочу, чтобы критик компилятора, когда я вызываю конструктор foo с классом , который НЕ получен из _base *. Текущий код позволяет использовать только foo < _base *>. Любое решение ?Специализация шаблона C++ через базовый класс

class _base 
{ 
public: 
    // ... 
}; 

class _derived: public _base 
{ 
public: 
    // ... 
}; 

template <typename T> 
class foo 
{ 
public: 
    foo()  { void TEMPLATE_ERROR; } 
}; 

template <> foo<_base*>::foo() 
{ 
    // this is the only constructor 
} 

основной код:

foo<_base*> a; // should work 
foo<_derived*> b; // should work (but doesnt) 
foo<int*>  c; // should not work (and infact doesnt) 

ответ

3

без Boost, вы можете использовать что-то вроде следующего, чтобы определить, является ли указатель на тип может быть неявно приведен к другому типу указателя на-:

template <class Derived, class Base> 
struct IsConvertible 
{ 
    template <class T> 
    static char test(T*); 

    template <class T> 
    static double test(...); 

    static const bool value = sizeof(test<Base>(static_cast<Derived*>(0))) == 1; 
}; 

Чтобы сделать это вызвать ошибку при compile- вы можете теперь использовать value в выражении, которое вызывает ошибку, если оно ложно, например typedef массив с отрицательным размером.

template <typename T> 
class foo 
{ 
public: 
    foo() 
    { 
     typedef T assert_at_compile_time[IsConvertible<T, _base>::value ? 1 : -1]; 
    } 
}; 
+0

aaah, спасибо. я попытался понять, что сам по себе погружаюсь в форд-джунгли, но я наткнулся на множество кодовых программ, поэтому мне пришлось отступить. Но это именно то, что я ищу, спасибо. –

+1

Я рекомендую вам прочитать «Modern C++ Design: Generic Programming and Design Patterns Applied» от Andrei Alexandrescu, если вы хотите узнать больше о связанных с шаблоном методах, подобных этому. –

+0

+1 Это действительно хороший. И спасибо за рекомендацию! –

4

Использование SFINAE (через enable_if) и подталкивания-х is_convertible type trait:

template <typename T, typename Enabled = void> 
class foo 
{ 
private: 
    foo(); // Constructor declared private and not implemented. 
}; 

template <typename T> 
class foo<T, typename enable_if<is_convertible<T, _base*> >::type> 
{ 
public: 
    foo() { /* regular code */ } 
}; 

(. Проверялось, нет наддува установлен на этой машине)

+0

Thanx, я прочитал ссылки, и они вызвали некоторые мысли. Должно быть хорошим решением, но я пока не использую boost. –

+0

Красота Boost заключается в том, что вы можете использовать только ее части - в частности, большинство заголовков можно просто скопировать в каталог вашего проекта или в каталог с системой. –

1

Я понимаю, что вы не используете boost в своем проекте, но, возможно, вы можете скопируйте-вставьте некоторые его части.

я нашел простое решение вашей проблемы с помощью повышения:

template <typename T> 
class foo 
{ 
public: 
    foo() { 
     BOOST_STATIC_ASSERT((boost::is_convertible<T,_base*>::value)); 
    } 
}; 

Он не требует дополнительного параметра шаблона, также нет необходимости в специализации шаблона. Я тестировал его с повышением 1.40.

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

  • Нет связанных вопросов^_^