如何在C++编译时检查运算符的特定重载是否存在



我有一个类,它重载了多种输入类型的 (( 运算符,即

struct Type {
    void operator()(int);
    void operator()(std::string);
};

现在,我想使用 SFINAE 来检查是否存在 (( 运算符的特定重载,即

if (Type()(std::string) overload exists) {
    // do something...
}

这在 C++11 中可以做到吗?(我不能使用 C++14 或 C++17(。

注意:在实际代码中,有一个模板类接受具有某些属性的类类型。此模板中有一个成员函数,该函数将根据参数类型的 (( 运算符的某些特定重载是否存在进行专用。

使用 SFINAE 检查是否可以将指向要查找的operator()重载的成员进行指针。

以下是我将如何做到这一点:

#include <type_traits>
template <typename A, typename B, typename = void>
struct has_overload : std::false_type {};
template <typename A, typename B>
struct has_overload<A, B, decltype((void)(void (A::*)(B))&A::operator())> : std::true_type {};

用法: has_overload<Type, std::string>::value .

第一步,我将Type::opeator()限制为仅采用特定类型,即 intstring .

struct Type {
    void operator()(int) {}
    void operator()(std::string) {}
    template<class U>
    void operator()(U) = delete;
};

通过这种方式,我们禁用隐式转换。

然后我们可以编写这样的类模板:

template<class T, class = void>
struct canInvokeFor : std::false_type {};
template<class Arg>
struct canInvokeFor< Arg, decltype ( std::declval<Type>().operator ()(Arg{}) ) > 
   : std::true_type {};

在其专业化中,我们模拟为传递的Arg类型调用operator()。结果:

struct Foo {};
std::cout << canInvokeFor<int>::value << std::endl; // 1
std::cout << canInvokeFor<std::string>::value << std::endl; // 1
std::cout << canInvokeFor<float>::value << std::endl; // 0
std::cout << canInvokeFor<char>::value << std::endl; // 0
std::cout << canInvokeFor<Foo>::value << std::endl; // 0

在 c++11 下演示

相关内容

  • 没有找到相关文章

最新更新