#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_static_foo, T::foo, void (*)(void)); // signature is the important part for static. it is not (T::*)
 
class StaticFoo
{
public:
    static void foo();
};
 
class Foo
{
public:
    void foo();
};
 
class Bar
{
};
 
static_assert(has_static_foo<StaticFoo>::value, "");
static_assert(!has_static_foo<Foo>::value, "");
static_assert(!has_static_foo<Bar>::value, "");
 
int main()
{}
 
				I2luY2x1ZGUgPGNzdGRpbnQ+CgojZGVmaW5lIERFRklORV9IQVNfU0lHTkFUVVJFKHRyYWl0c05hbWUsIGZ1bmNOYW1lLCBzaWduYXR1cmUpICAgICAgICAgICAgICAgXAogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFU+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgY2xhc3MgdHJhaXRzTmFtZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgcHJpdmF0ZTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQsIFQ+IHN0cnVjdCBoZWxwZXI7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQ+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIHN0YXRpYyBzdGQ6OnVpbnQ4X3QgY2hlY2soaGVscGVyPHNpZ25hdHVyZSwgJmZ1bmNOYW1lPiopOyAgICAgICAgICAgXAogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQ+IHN0YXRpYyBzdGQ6OnVpbnQxNl90IGNoZWNrKC4uLik7ICAgICAgICAgICAgICAgXAogICAgcHVibGljOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIHN0YXRpYyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgIGNvbnN0ZXhwciBib29sIHZhbHVlID0gc2l6ZW9mKGNoZWNrPFU+KDApKSA9PSBzaXplb2Yoc3RkOjp1aW50OF90KTsgXAogICAgfQoKREVGSU5FX0hBU19TSUdOQVRVUkUoaGFzX3N0YXRpY19mb28sIFQ6OmZvbywgdm9pZCAoKikodm9pZCkpOyAvLyBzaWduYXR1cmUgaXMgdGhlIGltcG9ydGFudCBwYXJ0IGZvciBzdGF0aWMuIGl0IGlzIG5vdCAoVDo6KikKCmNsYXNzIFN0YXRpY0Zvbwp7CnB1YmxpYzoKICAgIHN0YXRpYyB2b2lkIGZvbygpOwp9OwoKY2xhc3MgRm9vCnsKcHVibGljOgogICAgdm9pZCBmb28oKTsKfTsKCmNsYXNzIEJhcgp7Cn07CgpzdGF0aWNfYXNzZXJ0KGhhc19zdGF0aWNfZm9vPFN0YXRpY0Zvbz46OnZhbHVlLCAiIik7CnN0YXRpY19hc3NlcnQoIWhhc19zdGF0aWNfZm9vPEZvbz46OnZhbHVlLCAiIik7CnN0YXRpY19hc3NlcnQoIWhhc19zdGF0aWNfZm9vPEJhcj46OnZhbHVlLCAiIik7CgppbnQgbWFpbigpCnt9Cg==