#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