#include <cstdint>
#include <iostream>
template <typename U>
class has_special
{
private:
template<typename T, typename = typename T::special>
static std::uint8_t check(int);
template<typename T> static std::uint16_t check(...);
public:
static
constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t);
};
struct NormalType { };
struct SpecialType { typedef int special; };
static_assert(has_special<SpecialType>::value, "");
static_assert(!has_special<NormalType>::value, "");
template <typename T, bool = has_special<T>::value>
struct DetectSpecial {
void detected() { std::cout << "Not special...\n"; }
};
template <typename T>
struct DetectSpecial<T, true> {
void detected() { std::cout << "Special!\n"; }
};
int main()
{
DetectSpecial<NormalType>().detected();
DetectSpecial<SpecialType>().detected();
return 0;
}
I2luY2x1ZGUgPGNzdGRpbnQ+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnRlbXBsYXRlIDx0eXBlbmFtZSBVPgpjbGFzcyBoYXNfc3BlY2lhbAp7CnByaXZhdGU6CiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSA9IHR5cGVuYW1lIFQ6OnNwZWNpYWw+CiAgICBzdGF0aWMgc3RkOjp1aW50OF90IGNoZWNrKGludCk7CiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBUPiBzdGF0aWMgc3RkOjp1aW50MTZfdCBjaGVjayguLi4pOwpwdWJsaWM6CiAgICBzdGF0aWMKICAgIGNvbnN0ZXhwciBib29sIHZhbHVlID0gc2l6ZW9mKGNoZWNrPFU+KDApKSA9PSBzaXplb2Yoc3RkOjp1aW50OF90KTsKfTsKCnN0cnVjdCBOb3JtYWxUeXBlIHsgfTsKc3RydWN0IFNwZWNpYWxUeXBlIHsgdHlwZWRlZiBpbnQgc3BlY2lhbDsgfTsKCnN0YXRpY19hc3NlcnQoaGFzX3NwZWNpYWw8U3BlY2lhbFR5cGU+Ojp2YWx1ZSwgIiIpOwpzdGF0aWNfYXNzZXJ0KCFoYXNfc3BlY2lhbDxOb3JtYWxUeXBlPjo6dmFsdWUsICIiKTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBULCBib29sID0gaGFzX3NwZWNpYWw8VD46OnZhbHVlPgpzdHJ1Y3QgRGV0ZWN0U3BlY2lhbCB7CiAgICB2b2lkIGRldGVjdGVkKCkgeyBzdGQ6OmNvdXQgPDwgIk5vdCBzcGVjaWFsLi4uXG4iOyB9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IERldGVjdFNwZWNpYWw8VCwgdHJ1ZT4gewogICAgdm9pZCBkZXRlY3RlZCgpIHsgc3RkOjpjb3V0IDw8ICJTcGVjaWFsIVxuIjsgfQp9OwoKaW50IG1haW4oKQp7CiAgICBEZXRlY3RTcGVjaWFsPE5vcm1hbFR5cGU+KCkuZGV0ZWN0ZWQoKTsKICAgIERldGVjdFNwZWNpYWw8U3BlY2lhbFR5cGU+KCkuZGV0ZWN0ZWQoKTsKCiAgICByZXR1cm4gMDsKfQoK