#include <iostream>
template <typename... Ts> void foo_void(Ts...) = delete;
void foo_void() { std::cout << "foo void" << std::endl; }
template <typename... Ts> void foo_int(Ts...) = delete;
void foo_int(int) { std::cout << "foo int" << std::endl; }
void foo_both(int) { std::cout << "foo_both int" << std::endl; }
void foo_both() { std::cout << "foo_both void" << std::endl; }
namespace detail
{
struct tag1
{
};
struct tag : tag1
{
};
}
#define CALL(name) \
namespace detail \
{ \
template <typename Int> auto call_##name(Int i, tag1) -> decltype(name(i)) { return name(i); } \
\
template <typename Int> auto call_##name(Int, tag) -> decltype(sizeof(Int), name()) { return name(); } \
} \
\
void call_##name(int i) { return detail::call_##name(i, detail::tag{}); }
CALL(foo_int)
CALL(foo_void)
CALL(foo_both)
int main()
{
call_foo_void(42);
call_foo_int(42);
call_foo_both(42);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHR5cGVuYW1lLi4uIFRzPiB2b2lkIGZvb192b2lkKFRzLi4uKSA9IGRlbGV0ZTsKdm9pZCBmb29fdm9pZCgpIHsgc3RkOjpjb3V0IDw8ICJmb28gdm9pZCIgPDwgc3RkOjplbmRsOyB9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4gVHM+IHZvaWQgZm9vX2ludChUcy4uLikgPSBkZWxldGU7CnZvaWQgZm9vX2ludChpbnQpIHsgc3RkOjpjb3V0IDw8ICJmb28gaW50IiA8PCBzdGQ6OmVuZGw7IH0KCnZvaWQgZm9vX2JvdGgoaW50KSB7IHN0ZDo6Y291dCA8PCAiZm9vX2JvdGggaW50IiA8PCBzdGQ6OmVuZGw7IH0Kdm9pZCBmb29fYm90aCgpIHsgc3RkOjpjb3V0IDw8ICJmb29fYm90aCB2b2lkIiA8PCBzdGQ6OmVuZGw7IH0KCm5hbWVzcGFjZSBkZXRhaWwKewpzdHJ1Y3QgdGFnMQp7Cn07CnN0cnVjdCB0YWcgOiB0YWcxCnsKfTsKfQoKI2RlZmluZSBDQUxMKG5hbWUpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgIG5hbWVzcGFjZSBkZXRhaWwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgICAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgSW50PiBhdXRvIGNhbGxfIyNuYW1lKEludCBpLCB0YWcxKSAtPiBkZWNsdHlwZShuYW1lKGkpKSB7IHJldHVybiBuYW1lKGkpOyB9ICAgICAgIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgICAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgSW50PiBhdXRvIGNhbGxfIyNuYW1lKEludCwgdGFnKSAtPiBkZWNsdHlwZShzaXplb2YoSW50KSwgbmFtZSgpKSB7IHJldHVybiBuYW1lKCk7IH0gXAogICAgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgdm9pZCBjYWxsXyMjbmFtZShpbnQgaSkgeyByZXR1cm4gZGV0YWlsOjpjYWxsXyMjbmFtZShpLCBkZXRhaWw6OnRhZ3t9KTsgfQoKQ0FMTChmb29faW50KQpDQUxMKGZvb192b2lkKQpDQUxMKGZvb19ib3RoKQoKaW50IG1haW4oKQp7CiAgICBjYWxsX2Zvb192b2lkKDQyKTsKICAgIGNhbGxfZm9vX2ludCg0Mik7CiAgICBjYWxsX2Zvb19ib3RoKDQyKTsKfQo=