Вы можете сделать это, используя SFINAE, но это волшебно, если вы не знаете, что происходит ...
template<typename T> class Wrap { };
struct myclass {};
struct X {};
class Int : public Wrap<int> { /* ... */ };
class MyClass : public Wrap<myclass> { /* ... */ };
template< typename X >
struct is_derived_from_Wrap
{
struct true_type { char _[1]; };
struct false_type { char _[2]; };
template< typename U >
static true_type test_sfinae( Wrap<U> * w);
static false_type test_sfinae( ... );
enum { value = sizeof( test_sfinae( (X*)(0) ) )==sizeof(true_type) };
};
#include <iostream>
#define test(X,Y) std::cout<<( #X " == " #Y )<<" : "<<( (X)?"true":"false") <<std::endl;
int main()
{
test(is_derived_from_Wrap <Int>::value, true);
test(is_derived_from_Wrap <MyClass>::value, true);
test(is_derived_from_Wrap <char>::value, false);
test(is_derived_from_Wrap <X>::value, false);
}
Это дает ожидаемый результат
is_derived_from_Wrap <Int>::value == true : true
is_derived_from_Wrap <MyClass>::value == true : true
is_derived_from_Wrap <char>::value == false : false
is_derived_from_Wrap <X>::value == false : false
Есть пара ошибок с моим кодом. Он также вернет true, если тип является Wrap.
assert( is_derived_from_Wrap< Wrap<char> >::value == 1 );
Возможно, это можно исправить, используя немного больше магии SFINAE, если необходимо.
Будет возвращено значение false, если деривация не является публичной деривацией (т.е. является частной или защищенной)
struct Evil : private Wrap<T> { };
assert( is_derived_from_Wrap<Evil>::value == 0 );
Я подозреваю, что это не может быть исправлено. (Но я могу ошибаться). Но я подозреваю, что публичного наследства достаточно.