#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);
}
