C ++编译时检查可以使用某种类型的参数调用重载函数

5r1*_*Oi1 5 c++

考虑重载函数

void f(int);
void f(long);
void f(double);
void f(MyClass);
Run Code Online (Sandbox Code Playgroud)

以及未知参数类型的模板类中的方法

template <class T>
struct C {
  void method(T arg) { ... }
};
Run Code Online (Sandbox Code Playgroud)

我想在编译时检查是否有一个版本f可以arg作为参数。

template <class T>
struct C {
  void method(T arg) { 
    if constexpr (CAN_BE_CALLED(f, arg)) {
      f(arg);
    } else {
      g();
    }
  }
};
Run Code Online (Sandbox Code Playgroud)

有可能这样做吗?我想这个这个,但编译器抱怨没有得到解决重载函数类型

Pas*_* By 6

您可以使用检测习语来构建这样的测试

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;
Run Code Online (Sandbox Code Playgroud)

并将其用作

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

居住

或者替代地

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...>;
Run Code Online (Sandbox Code Playgroud)