c++ - 通过模板调用可能不存在的成员函数

标签 c++ templates

如何通过模板技术调用可能存在的成员函数,我不想使用虚方法,因为类是任意的。

例如:

class A {
    void setValue(int value);
};

如何定义一个模板来调用类 A 的 setValue(如果它存在),否则什么也不做。

模板是这样的:

template <typename T>
struct call_if_exist {
    void invokeOrNot(T& a, int value){ // EXISTING: setValue
        a.setValue(value);
    }
}
template <typename T>
struct call_if_exist {
    void invokeOrNot(T& a, int value){ // NOT EXISTING: do nothing
    }
}

这是关于调用,而不是检查。

最佳答案

您可以利用 SFINAE制作一个类模板 checks for the existence of a member function in a given class ,并将结果用作 bool 标志,以针对没有函数的情况和成员函数存在的情况专门化您的模板:

template<typename T , bool member_exists = has_set_value<T>::result>
struct call_if_exist;

template <typename T>
struct call_if_exist<T,true> {
    void invokeOrNot(T& a, int value){ // EXISTING: setValue
        a.setValue(value);
    }
}
template <typename T>
struct call_if_exist<T,false> {
    void invokeOrNot(T& a, int value){ // NOT EXISTING: do nothing
    }
}

编辑:has_set_value性状

template<typename T>
class has_set_value
{
    typedef struct{ char c[1]; } yes;
    typedef struct{ char c[2]; } no;

    template<typename U> static yes test(&U::set_value);
    template<typename U> static no  test(...);

public:
    static const bool result = sizeof( test<T>(NULL) ) == sizeof( yes );
};

该类是使用SFINAE检查某个类的成员(类型或函数)是否存在的典型例子。

首先我们定义两个类型定义,yesno , 用于通过 sizeof 区分过载决议运营商。
test() 的第一次重载有一个指向成员函数的指针作为参数,最后一个是一个重载,目标是被所有不是指向成员的指针调用。这是通过可变参数函数(注意省略号)完成的,它可以与任何类型的参数一起使用。

实现的要点是即使第二个重载可以包含任何参数,第一个是指向我们成员函数的指针的显式情况。所以如果参数可以是指向函数的指针, 调用被解析为第一个函数,否则它被解析为第二个。

正如我之前所说,我们使用 typedef 通过 sizeof 来区分重载决议。运算符:请注意,第一个重载返回 yes和后来的返回no . 因此如果调用test() 的结果类型的大小使用指针 (NULL) 等于 yes 的大小, 意味着重载被解析为第一个,并且作为参数传递的类 ( T ) 有一个名为 set_value 的成员函数.

Alexandrescu's Modern C++ Dessigncheck if one type is implicitly convertible to other 的第二章中包含了此类特征的示例.

关于c++ - 通过模板调用可能不存在的成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18682409/

相关文章:

c++ - 整齐地约束 API 模板类型

c++ - 不能在从 std::vector 继承的类中使用 typedef 迭代器

c++ - 确定不同字符的数量

c++ - 在 C++ 中使用指针更改字符串值

c++ - 识别图像补丁 - 需要建议

c++ - 嵌套模板函数的重载

模板化类的模板化构造函数的 C++ 显式模板特化

c++ - 段错误(可能是由于转换)

c++ - 循环真的比递归快吗?

templates - 新 api 应用程序资源的 Azure 资源模板