#include <iostream>
using namespace std;
template <typename T>
class Base
{
public:
T* t;
void b() {}
};
class D1:
public Base<D1>
{
public:
int d1;
};
class D2:
public D1
{
public:
int d2;
};
template<template<typename> class Base, typename T>
struct IsAnyPublicBaseOf
{
typedef char (&yes)[2];
template<typename X>
static yes Check (Base<X>*);
static char Check (...);
static const bool value = (sizeof(Check((T*)0)) == sizeof(yes));
};
template<bool> struct Bool;
template <typename T, typename = Bool<true> >
class Selector
{
public:
template <typename U>
void a(U& u)
{
cout << "a(U&)" << endl;
}
};
template<typename T>
class Selector<T,Bool<IsAnyPublicBaseOf<Base,T>::value> >
{
public:
template <typename U>
void a(Base<U>& base)
{
cout << "a(Base<U>&)" << endl;
base.b();
}
};
int main()
{
D2 derivated;
Selector<D2> s;
s.a(derivated);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgpjbGFzcyBCYXNlCnsKICAgIHB1YmxpYzoKICAgICAgICBUKiB0OwogICAgICAgIHZvaWQgYigpIHt9Cn07CgpjbGFzcyBEMToKICAgICAgICBwdWJsaWMgQmFzZTxEMT4KewogICAgcHVibGljOgogICAgICAgIGludCBkMTsKfTsKCmNsYXNzIEQyOgogICAgICAgIHB1YmxpYyBEMQp7CiAgICBwdWJsaWM6CiAgICAgICAgaW50IGQyOwp9OwoKdGVtcGxhdGU8dGVtcGxhdGU8dHlwZW5hbWU+IGNsYXNzIEJhc2UsIHR5cGVuYW1lIFQ+CnN0cnVjdCBJc0FueVB1YmxpY0Jhc2VPZgp7CiAgdHlwZWRlZiBjaGFyICgmeWVzKVsyXTsKCiAgdGVtcGxhdGU8dHlwZW5hbWUgWD4KICBzdGF0aWMgeWVzIENoZWNrIChCYXNlPFg+Kik7CiAgc3RhdGljIGNoYXIgQ2hlY2sgKC4uLik7CgogIHN0YXRpYyBjb25zdCBib29sIHZhbHVlID0gKHNpemVvZihDaGVjaygoVCopMCkpID09IHNpemVvZih5ZXMpKTsKfTsKCnRlbXBsYXRlPGJvb2w+IHN0cnVjdCBCb29sOwp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgPSBCb29sPHRydWU+ID4KY2xhc3MgU2VsZWN0b3IKewpwdWJsaWM6CiAgdGVtcGxhdGUgPHR5cGVuYW1lIFU+CiAgdm9pZCBhKFUmIHUpCiAgewogICAgY291dCA8PCAiYShVJikiIDw8IGVuZGw7CiAgfQp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVD4KY2xhc3MgU2VsZWN0b3I8VCxCb29sPElzQW55UHVibGljQmFzZU9mPEJhc2UsVD46OnZhbHVlPiA+CnsKcHVibGljOgogIHRlbXBsYXRlIDx0eXBlbmFtZSBVPgogIHZvaWQgYShCYXNlPFU+JiBiYXNlKQogIHsKICAgIGNvdXQgPDwgImEoQmFzZTxVPiYpIiA8PCBlbmRsOwogICAgYmFzZS5iKCk7CiAgfQp9OwoKCmludCBtYWluKCkKewogICAgRDIgZGVyaXZhdGVkOwogICAgU2VsZWN0b3I8RDI+IHM7CiAgICBzLmEoZGVyaXZhdGVkKTsKICAgIHJldHVybiAwOwp9Cg==