#include <cstdint>
#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature) \
template <typename U> \
class traitsName \
{ \
private: \
template<typename T, T> struct helper; \
template<typename T> \
static std::uint8_t check(helper<signature, &funcName>*); \
template<typename T> static std::uint16_t check(...); \
public: \
static \
constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \
}
DEFINE_HAS_SIGNATURE(has_foo, T::foo, void (*)(void));
struct StaticFoo { static void foo(); };
struct NormalFoo { void foo(); };
struct NoFoo {};
static_assert(has_foo<StaticFoo>::value, "Unexpected value");
static_assert(!has_foo<NormalFoo>::value, "Unexpected value");
static_assert(!has_foo<NoFoo>::value, "Unexpected value");
int main()
{
return 0;
}
I2luY2x1ZGUgPGNzdGRpbnQ+CgojZGVmaW5lIERFRklORV9IQVNfU0lHTkFUVVJFKHRyYWl0c05hbWUsIGZ1bmNOYW1lLCBzaWduYXR1cmUpICAgICAgICAgICAgICAgXAogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFU+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgY2xhc3MgdHJhaXRzTmFtZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgcHJpdmF0ZTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQsIFQ+IHN0cnVjdCBoZWxwZXI7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQ+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIHN0YXRpYyBzdGQ6OnVpbnQ4X3QgY2hlY2soaGVscGVyPHNpZ25hdHVyZSwgJmZ1bmNOYW1lPiopOyAgICAgICAgICAgXAogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQ+IHN0YXRpYyBzdGQ6OnVpbnQxNl90IGNoZWNrKC4uLik7ICAgICAgICAgICAgICAgXAogICAgcHVibGljOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIHN0YXRpYyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIGNvbnN0ZXhwciBib29sIHZhbHVlID0gc2l6ZW9mKGNoZWNrPFU+KDApKSA9PSBzaXplb2Yoc3RkOjp1aW50OF90KTsgXAogICAgfQoKREVGSU5FX0hBU19TSUdOQVRVUkUoaGFzX2ZvbywgVDo6Zm9vLCB2b2lkICgqKSh2b2lkKSk7CgpzdHJ1Y3QgU3RhdGljRm9vIHsgc3RhdGljIHZvaWQgZm9vKCk7IH07CnN0cnVjdCBOb3JtYWxGb28geyB2b2lkIGZvbygpOyB9OwpzdHJ1Y3QgTm9Gb28ge307CgpzdGF0aWNfYXNzZXJ0KGhhc19mb288U3RhdGljRm9vPjo6dmFsdWUsICJVbmV4cGVjdGVkIHZhbHVlIik7CnN0YXRpY19hc3NlcnQoIWhhc19mb288Tm9ybWFsRm9vPjo6dmFsdWUsICJVbmV4cGVjdGVkIHZhbHVlIik7CnN0YXRpY19hc3NlcnQoIWhhc19mb288Tm9Gb28+Ojp2YWx1ZSwgIlVuZXhwZWN0ZWQgdmFsdWUiKTsKCmludCBtYWluKCkKewogICAgcmV0dXJuIDA7Cn0K