#include <type_traits>
#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_X, T::X, bool (T::*)());
DEFINE_HAS_SIGNATURE(has_Y, T::Y, bool (T::*)());
 
template <typename T>
typename std::enable_if<has_X<T>::value && has_Y<T>::value, bool>::type
func(T a)
{
  if(a.X())
    return a.Y();
  return false;
}
 
template <typename T>
typename std::enable_if<!has_X<T>::value || !has_Y<T>::value, bool>::type
func(T /*a*/)
{
    return false;
}
 
struct A {
    bool X() {return true;}
    bool Y() {return true;}
};
 
struct B {
};
 
int main()
{
    func<A>(A{});
    func<B>(B{});
 
    return 0;
}
 
				I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8Y3N0ZGludD4KCiNkZWZpbmUgREVGSU5FX0hBU19TSUdOQVRVUkUodHJhaXRzTmFtZSwgZnVuY05hbWUsIHNpZ25hdHVyZSkgICAgICAgICAgICAgICBcCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVT4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICBjbGFzcyB0cmFpdHNOYW1lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICBwcml2YXRlOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgVCwgVD4gc3RydWN0IGhlbHBlcjsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgVD4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgc3RhdGljIHN0ZDo6dWludDhfdCBjaGVjayhoZWxwZXI8c2lnbmF0dXJlLCAmZnVuY05hbWU+Kik7ICAgICAgICAgICBcCiAgICAgICAgdGVtcGxhdGU8dHlwZW5hbWUgVD4gc3RhdGljIHN0ZDo6dWludDE2X3QgY2hlY2soLi4uKTsgICAgICAgICAgICAgICBcCiAgICBwdWJsaWM6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgc3RhdGljICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICAgICAgY29uc3RleHByIGJvb2wgdmFsdWUgPSBzaXplb2YoY2hlY2s8VT4oMCkpID09IHNpemVvZihzdGQ6OnVpbnQ4X3QpOyBcCiAgICB9CgpERUZJTkVfSEFTX1NJR05BVFVSRShoYXNfWCwgVDo6WCwgYm9vbCAoVDo6KikoKSk7CkRFRklORV9IQVNfU0lHTkFUVVJFKGhhc19ZLCBUOjpZLCBib29sIChUOjoqKSgpKTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgp0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxoYXNfWDxUPjo6dmFsdWUgJiYgaGFzX1k8VD46OnZhbHVlLCBib29sPjo6dHlwZQpmdW5jKFQgYSkKewogIGlmKGEuWCgpKQogICAgcmV0dXJuIGEuWSgpOwogIHJldHVybiBmYWxzZTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPCFoYXNfWDxUPjo6dmFsdWUgfHwgIWhhc19ZPFQ+Ojp2YWx1ZSwgYm9vbD46OnR5cGUKZnVuYyhUIC8qYSovKQp7CiAgICByZXR1cm4gZmFsc2U7Cn0KCnN0cnVjdCBBIHsKICAgIGJvb2wgWCgpIHtyZXR1cm4gdHJ1ZTt9CiAgICBib29sIFkoKSB7cmV0dXJuIHRydWU7fQp9OwoKc3RydWN0IEIgewp9OwoKaW50IG1haW4oKQp7CiAgICBmdW5jPEE+KEF7fSk7CiAgICBmdW5jPEI+KEJ7fSk7CgogICAgcmV0dXJuIDA7Cn0K