#include <iostream>
struct H1{ void operator()() { std::cout << "H1" << std::endl; } };
struct H2{ void operator()() { std::cout << "H2" << std::endl; } };
typedef H1 default_H;
struct U2 { typedef H2 H; };
struct U1 { typedef H1 H; };
struct U0 {};
template < bool > struct bool_type {};
template <typename T>
class has_typedef_H {
typedef char no[1];
typedef char yes[2];
template <typename C>
static yes& test(typename C::H*);
template <typename>
static no& test(...);
public:
static const bool value = sizeof(yes) == sizeof(test<T>(0));
};
template<typename T,
typename = bool_type< true > >
struct H_type
{
typedef default_H type;
};
template<typename T>
struct H_type< T, bool_type< has_typedef_H< T >::value > >
{
typedef typename T::H type;
};
int main() {
H_type<U0>::type h0;
H_type<U1>::type h1;
H_type<U2>::type h2;
// Prints H1 H1 H2
h0();
h1();
h2();
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKc3RydWN0IEgxeyB2b2lkIG9wZXJhdG9yKCkoKSB7IHN0ZDo6Y291dCA8PCAiSDEiIDw8IHN0ZDo6ZW5kbDsgfSB9OwpzdHJ1Y3QgSDJ7IHZvaWQgb3BlcmF0b3IoKSgpIHsgc3RkOjpjb3V0IDw8ICJIMiIgPDwgc3RkOjplbmRsOyB9IH07Cgp0eXBlZGVmIEgxIGRlZmF1bHRfSDsKc3RydWN0IFUyIHsgdHlwZWRlZiBIMiBIOyB9OwpzdHJ1Y3QgVTEgeyB0eXBlZGVmIEgxIEg7IH07CnN0cnVjdCBVMCB7fTsKCnRlbXBsYXRlIDwgYm9vbCA+IHN0cnVjdCBib29sX3R5cGUge307Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KY2xhc3MgaGFzX3R5cGVkZWZfSCB7CiAgdHlwZWRlZiBjaGFyIG5vWzFdOwogIHR5cGVkZWYgY2hhciB5ZXNbMl07CgogIHRlbXBsYXRlIDx0eXBlbmFtZSBDPgogIHN0YXRpYyB5ZXMmIHRlc3QodHlwZW5hbWUgQzo6SCopOwoKICB0ZW1wbGF0ZSA8dHlwZW5hbWU+CiAgc3RhdGljIG5vJiB0ZXN0KC4uLik7CgpwdWJsaWM6CiAgc3RhdGljIGNvbnN0IGJvb2wgdmFsdWUgPSBzaXplb2YoeWVzKSA9PSBzaXplb2YodGVzdDxUPigwKSk7IAp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVCwgCiAgICAgICAgIHR5cGVuYW1lID0gYm9vbF90eXBlPCB0cnVlID4gPgpzdHJ1Y3QgSF90eXBlCnsKICB0eXBlZGVmIGRlZmF1bHRfSCB0eXBlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVD4Kc3RydWN0IEhfdHlwZTwgVCwgYm9vbF90eXBlPCBoYXNfdHlwZWRlZl9IPCBUID46OnZhbHVlID4gPgp7CiAgdHlwZWRlZiB0eXBlbmFtZSBUOjpIIHR5cGU7Cn07CgppbnQgbWFpbigpIHsKCiAgICBIX3R5cGU8VTA+Ojp0eXBlIGgwOwogICAgSF90eXBlPFUxPjo6dHlwZSBoMTsKICAgIEhfdHlwZTxVMj46OnR5cGUgaDI7CgogICAgLy8gUHJpbnRzIEgxIEgxIEgyCiAgICBoMCgpOwogICAgaDEoKTsKICAgIGgyKCk7CiAgICByZXR1cm4gMDsgCn0=