#include <iostream>
template <typename T>
struct is_foo {
private:
template<typename U, U> struct helper{};
template <typename Z> static auto test(Z z) -> decltype(
helper<void (Z::*)() const, &Z::foo>(),
// All other requirements follow..
std::true_type()
);
template <typename> static auto test(...) -> std::false_type;
public:
enum { value = std::is_same<decltype(test<T>(std::declval<T>())),std::true_type>::value };
};
struct A {
void foo() const;
};
struct A1 : public A {};
struct B { void foo(); };
struct C { int foo() const; };
template <typename T>
struct D : public T {};
int main() {
std::cout << "Good examples (should print 1)\n";
std::cout << is_foo<A>::value << '\n';
std::cout << is_foo<A1>::value << '\n';
std::cout << is_foo<D<A>>::value << '\n';
std::cout << is_foo<D<A1>>::value << '\n';
std::cout << "Bad examples (should print 0)\n";
std::cout << is_foo<B>::value << '\n';
std::cout << is_foo<C>::value << '\n';
std::cout << is_foo<D<B>>::value << '\n';
std::cout << is_foo<D<C>>::value << '\n';
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnN0cnVjdCBpc19mb28gewogICAgcHJpdmF0ZToKICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBVLCBVPiBzdHJ1Y3QgaGVscGVye307CgogICAgICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBaPiBzdGF0aWMgYXV0byB0ZXN0KFogeikgLT4gZGVjbHR5cGUoCgogICAgICAgICAgICAgICAgaGVscGVyPHZvaWQgKFo6OiopKCkgY29uc3QsICAgICAgICAgICAgICAgICAgICAgICAmWjo6Zm9vPigpLAogICAgICAgICAgICAgICAgLy8gQWxsIG90aGVyIHJlcXVpcmVtZW50cyBmb2xsb3cuLgoKICAgICAgICAgICAgICAgIHN0ZDo6dHJ1ZV90eXBlKCkKICAgICAgICAgICAgICAgICk7CgogICAgICAgIHRlbXBsYXRlIDx0eXBlbmFtZT4gc3RhdGljIGF1dG8gdGVzdCguLi4pIC0+IHN0ZDo6ZmFsc2VfdHlwZTsKCiAgICBwdWJsaWM6CiAgICAgICAgZW51bSB7IHZhbHVlID0gc3RkOjppc19zYW1lPGRlY2x0eXBlKHRlc3Q8VD4oc3RkOjpkZWNsdmFsPFQ+KCkpKSxzdGQ6OnRydWVfdHlwZT46OnZhbHVlIH07Cn07CgpzdHJ1Y3QgQSB7IAogICAgdm9pZCBmb28oKSBjb25zdDsgCn07CgpzdHJ1Y3QgQTEgOiBwdWJsaWMgQSB7fTsKCnN0cnVjdCBCIHsgdm9pZCBmb28oKTsgfTsKc3RydWN0IEMgeyBpbnQgZm9vKCkgY29uc3Q7IH07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IEQgOiBwdWJsaWMgVCB7fTsKCmludCBtYWluKCkgewogICAgc3RkOjpjb3V0IDw8ICJHb29kIGV4YW1wbGVzIChzaG91bGQgcHJpbnQgMSlcbiI7CiAgICBzdGQ6OmNvdXQgPDwgaXNfZm9vPEE+Ojp2YWx1ZSAgICAgICA8PCAnXG4nOyAgICAKICAgIHN0ZDo6Y291dCA8PCBpc19mb288QTE+Ojp2YWx1ZSAgICAgIDw8ICdcbic7ICAgCiAgICBzdGQ6OmNvdXQgPDwgaXNfZm9vPEQ8QT4+Ojp2YWx1ZSAgICA8PCAnXG4nOyAKICAgIHN0ZDo6Y291dCA8PCBpc19mb288RDxBMT4+Ojp2YWx1ZSAgIDw8ICdcbic7CgogICAgc3RkOjpjb3V0IDw8ICJCYWQgZXhhbXBsZXMgKHNob3VsZCBwcmludCAwKVxuIjsKICAgIHN0ZDo6Y291dCA8PCBpc19mb288Qj46OnZhbHVlICAgICAgIDw8ICdcbic7CiAgICBzdGQ6OmNvdXQgPDwgaXNfZm9vPEM+Ojp2YWx1ZSAgICAgICA8PCAnXG4nOwogICAgc3RkOjpjb3V0IDw8IGlzX2ZvbzxEPEI+Pjo6dmFsdWUgICAgPDwgJ1xuJzsKICAgIHN0ZDo6Y291dCA8PCBpc19mb288RDxDPj46OnZhbHVlICAgIDw8ICdcbic7CgogICAgcmV0dXJuIDA7Cn0K