#include <utility>
#define AUTO_RETURN( ... ) -> decltype(__VA_ARGS__) { return (__VA_ARGS__); }
struct base_tag {};
struct derived_tag : base_tag {};
template< typename F,
typename T1,
typename...
Args >
auto invoke( derived_tag, F f, T1&& t1, Args&&... args )
AUTO_RETURN( (std::forward<T1>(t1).*f)(std::forward<Args>(args)...) )
template< typename F,
typename T1,
typename... Args >
auto invoke( base_tag, F f, T1 t1, Args&&... args )
AUTO_RETURN( ((*t1).*f)(std::forward<Args>(args)...) )
template< typename F,
typename T1 >
auto invoke( base_tag, F f, T1&& t1 )
AUTO_RETURN( std::forward<T1>(t1).*f )
template< typename F,
typename T1 >
auto invoke( base_tag, F f, T1 t1 )
AUTO_RETURN( (*t1).*f )
template< typename F, typename... Args >
auto invoke( base_tag, F&& f, Args&&... args )
{
return std::forward<F>(f)(std::forward<Args>(args)...);
}
template< typename... Args >
auto INVOKE( Args&&... args )
{
return invoke( derived_tag{}, std::forward<Args>(args)... );
}
struct wat { wat& operator*() { return *this; } void foo(){} };;
int main()
{
INVOKE(&wat::foo, wat{});
}
I2luY2x1ZGUgPHV0aWxpdHk+CgojZGVmaW5lIEFVVE9fUkVUVVJOKCAuLi4gKSAtPiBkZWNsdHlwZShfX1ZBX0FSR1NfXykgeyByZXR1cm4gKF9fVkFfQVJHU19fKTsgfQoKc3RydWN0IGJhc2VfdGFnIHt9OwpzdHJ1Y3QgZGVyaXZlZF90YWcgOiBiYXNlX3RhZyB7fTsKCnRlbXBsYXRlPCB0eXBlbmFtZSBGLAogICAgICAgICAgdHlwZW5hbWUgVDEsCiAgICAgICAgICB0eXBlbmFtZS4uLgogICAgICAgICAgIEFyZ3MgPgphdXRvIGludm9rZSggZGVyaXZlZF90YWcsIEYgZiwgVDEmJiB0MSwgQXJncyYmLi4uIGFyZ3MgKQpBVVRPX1JFVFVSTiggIChzdGQ6OmZvcndhcmQ8VDE+KHQxKS4qZikoc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uKSAgKQoKdGVtcGxhdGU8IHR5cGVuYW1lIEYsCiAgICAgICAgICB0eXBlbmFtZSBUMSwKICAgICAgICAgIHR5cGVuYW1lLi4uIEFyZ3MgPgphdXRvIGludm9rZSggYmFzZV90YWcsIEYgZiwgVDEgdDEsIEFyZ3MmJi4uLiBhcmdzICkKQVVUT19SRVRVUk4oICAoKCp0MSkuKmYpKHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLikgICkKCnRlbXBsYXRlPCB0eXBlbmFtZSBGLAogICAgICAgICAgdHlwZW5hbWUgVDEgPgphdXRvIGludm9rZSggYmFzZV90YWcsIEYgZiwgVDEmJiB0MSApCkFVVE9fUkVUVVJOKCAgc3RkOjpmb3J3YXJkPFQxPih0MSkuKmYgICkKCnRlbXBsYXRlPCB0eXBlbmFtZSBGLAogICAgICAgICAgdHlwZW5hbWUgVDEgPgphdXRvIGludm9rZSggYmFzZV90YWcsIEYgZiwgVDEgdDEgKQpBVVRPX1JFVFVSTiggICgqdDEpLipmICApCgp0ZW1wbGF0ZTwgdHlwZW5hbWUgRiwgdHlwZW5hbWUuLi4gQXJncyA+CmF1dG8gaW52b2tlKCBiYXNlX3RhZywgRiYmIGYsIEFyZ3MmJi4uLiBhcmdzICkKewogICAgcmV0dXJuIHN0ZDo6Zm9yd2FyZDxGPihmKShzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykuLi4pOwp9Cgp0ZW1wbGF0ZTwgdHlwZW5hbWUuLi4gQXJncyA+CmF1dG8gSU5WT0tFKCBBcmdzJiYuLi4gYXJncyApCnsKICAgIHJldHVybiBpbnZva2UoIGRlcml2ZWRfdGFne30sIHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLiApOwp9CgpzdHJ1Y3Qgd2F0IHsgd2F0JiBvcGVyYXRvciooKSB7IHJldHVybiAqdGhpczsgfSB2b2lkIGZvbygpe30gfTs7CgppbnQgbWFpbigpCnsKICAgIElOVk9LRSgmd2F0Ojpmb28sIHdhdHt9KTsKfQo=