C++ Compile-time check that an overloaded function can be called with a certain type of argument

You could use the detection idiom to build such a test

template<typename = void, typename... Args>
struct test : std::false_type {};

template<typename... Args>
struct test<std::void_t<decltype(f(std::declval<Args>()...))>, Args...>
    : std::true_type {};

template<typename... Args>
inline constexpr bool test_v = test<void, Args...>::value;

And use it as

template <class T>
struct C
{
    void method(T arg)
    { 
        if constexpr (test_v<T>)
            f(arg);
        else
            g();
    }
};

Live

Or alternatively

template<typename... Args>
using test_t = decltype(f(std::declval<Args>()...));

template<typename... Args>
inline constexpr auto test_v = std::experimental::is_detected_v<test_t, Args...>;

You might do the following with SFINAE:

template <class T, typename Enabler = void>
struct C {
    void method(T arg) {
        g();
    }
};

template <class T>
struct C<T, std::void_t<decltype(f(std::declval<T>()))>> {
    void method(T arg) { 
        f(arg);
    }
};

Demo

Tags:

C++