#include <iostream>
#include <type_traits>
template < template < class > class T, class U>
struct isDerivedFrom
{
static constexpr bool value = decltype( isDerivedFrom:: test ( std:: declval < U> ( ) ) ) :: value ;
private :
template < class V>
static decltype( static_cast < T< V>> ( std:: declval < U> ( ) ) , std:: true_type { } ) test( const T< V> & ) ;
static std:: false_type test( ...) ;
} ;
template < class T>
struct Base { } ;
struct Base_D1 : Base< int > { } ;
struct Base_D2 : Base< Base_D2> { } ;
struct Base_D1_D1 : Base_D1 { } ;
struct NotDerived { } ;
template < typename T>
struct Base2 { protected : Base2( ) { } } ;
struct Derived2 : private Base2< int > { } ;
int main( )
{
std:: cout << std:: boolalpha
<< "is Base_D1 derived from or a template instantiation of Base: "
<< isDerivedFrom< Base, Base_D1> :: value << "\n "
<< "is Base_D2 derived from or a template instantiation of Base: "
<< isDerivedFrom< Base, Base_D2> :: value << "\n "
<< "is Base_D1_D1 derived from or a template instantiation of Base: "
<< isDerivedFrom< Base, Base_D1_D1> :: value << "\n "
<< "is Base<double> derived from or a template instantiation of Base: "
<< isDerivedFrom< Base, Base< double >> :: value << "\n "
<< "is NotDerived derived from or a template instantiation of Base: "
<< isDerivedFrom< Base, NotDerived> :: value << "\n "
<< "is Derived2 derived from or a template instantiation of Base2: "
<< isDerivedFrom< Base2, Derived2> :: value << "\n " ;
return 0 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZTx0ZW1wbGF0ZTxjbGFzcz4gY2xhc3MgVCwgY2xhc3MgVT4Kc3RydWN0IGlzRGVyaXZlZEZyb20KewogICAgc3RhdGljIGNvbnN0ZXhwciBib29sIHZhbHVlID0gZGVjbHR5cGUoaXNEZXJpdmVkRnJvbTo6dGVzdChzdGQ6OmRlY2x2YWw8VT4oKSkpOjp2YWx1ZTsKcHJpdmF0ZToKICAgIHRlbXBsYXRlPGNsYXNzIFY+CiAgICBzdGF0aWMgZGVjbHR5cGUoc3RhdGljX2Nhc3Q8VDxWPj4oc3RkOjpkZWNsdmFsPFU+KCkpLCBzdGQ6OnRydWVfdHlwZXt9KSB0ZXN0KGNvbnN0IFQ8Vj4mKTsKICAgIHN0YXRpYyBzdGQ6OmZhbHNlX3R5cGUgdGVzdCguLi4pOwp9OwoKdGVtcGxhdGU8Y2xhc3MgVD4Kc3RydWN0IEJhc2Uge307CnN0cnVjdCBCYXNlX0QxIDogQmFzZTxpbnQ+IHt9OwpzdHJ1Y3QgQmFzZV9EMiA6IEJhc2U8QmFzZV9EMj4ge307CnN0cnVjdCBCYXNlX0QxX0QxIDogQmFzZV9EMSB7fTsKc3RydWN0IE5vdERlcml2ZWQge307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IEJhc2UyIHtwcm90ZWN0ZWQ6IEJhc2UyKCl7fX07CnN0cnVjdCBEZXJpdmVkMiA6IHByaXZhdGUgQmFzZTI8aW50PiB7fTsKCmludCBtYWluKCkKewogICAgc3RkOjpjb3V0IDw8IHN0ZDo6Ym9vbGFscGhhCiAgICAgICAgPDwgImlzIEJhc2VfRDEgZGVyaXZlZCBmcm9tIG9yIGEgdGVtcGxhdGUgaW5zdGFudGlhdGlvbiBvZiBCYXNlOiAiCiAgICAgICAgPDwgaXNEZXJpdmVkRnJvbTxCYXNlLCBCYXNlX0QxPjo6dmFsdWUgPDwgIlxuIgogICAgICAgIDw8ICJpcyBCYXNlX0QyIGRlcml2ZWQgZnJvbSBvciBhIHRlbXBsYXRlIGluc3RhbnRpYXRpb24gb2YgQmFzZTogIgogICAgICAgIDw8IGlzRGVyaXZlZEZyb208QmFzZSwgQmFzZV9EMj46OnZhbHVlIDw8ICJcbiIKICAgICAgICA8PCAiaXMgQmFzZV9EMV9EMSBkZXJpdmVkIGZyb20gb3IgYSB0ZW1wbGF0ZSBpbnN0YW50aWF0aW9uIG9mIEJhc2U6ICIKICAgICAgICA8PCBpc0Rlcml2ZWRGcm9tPEJhc2UsIEJhc2VfRDFfRDE+Ojp2YWx1ZSA8PCAiXG4iCiAgICAgICAgPDwgImlzIEJhc2U8ZG91YmxlPiBkZXJpdmVkIGZyb20gb3IgYSB0ZW1wbGF0ZSBpbnN0YW50aWF0aW9uIG9mIEJhc2U6ICIKICAgICAgICA8PCBpc0Rlcml2ZWRGcm9tPEJhc2UsIEJhc2U8ZG91YmxlPj46OnZhbHVlIDw8ICJcbiIKICAgICAgICA8PCAiaXMgTm90RGVyaXZlZCBkZXJpdmVkIGZyb20gb3IgYSB0ZW1wbGF0ZSBpbnN0YW50aWF0aW9uIG9mIEJhc2U6ICIKICAgICAgICA8PCBpc0Rlcml2ZWRGcm9tPEJhc2UsIE5vdERlcml2ZWQ+Ojp2YWx1ZSA8PCAiXG4iCgogICAgICAgIDw8ICJpcyBEZXJpdmVkMiBkZXJpdmVkIGZyb20gb3IgYSB0ZW1wbGF0ZSBpbnN0YW50aWF0aW9uIG9mIEJhc2UyOiAiCiAgICAgICAgPDwgaXNEZXJpdmVkRnJvbTxCYXNlMiwgRGVyaXZlZDI+Ojp2YWx1ZSA8PCAiXG4iOwogICAgcmV0dXJuIDA7Cn0K