是否有可能制作一个具有NULL检查的通用c++函数指针包装器?

Is it possible to make a generic C++ function pointer wrapper with NULL checks?

本文关键字:检查 c++ 函数 包装 指针 NULL 有可能 一个 是否      更新时间:2023-10-16

我必须包装几个函数指针,可以有NULL值。我试图为此制作一个通用的类模板,它检查函数指针是否为NULL,如果指针不为NULL则调用原始函数,如果指针为NULL则返回默认值。像这样:

//Function typedefs
typedef void(*foo)();
typedef int(*bar)(int u, char *);
//Function pointers
foo gfFoo;
bar gfBar;
//Wrapper class
template<typename T,  typename... Args>
class WrapFuncObj {
    T* f;
public:
    WrapFuncObj(T* t) {
        f = t;
    }
    typename std::result_of<T(Args...)>::type operator()(Args&&... args) {
        if(f != nullptr){
            return (*f)(std::forward<Args>(args)...);
        }
        else
        {
            return 0; //RETURN something for non-void types
        }
    }
};
template<typename T,  typename... Args>
class WrapFuncObjVoid {
    T* f;
public:
    WrapFuncObjVoid(T* t) {
        f = t;
    }
    typename std::result_of<T(Args...)>::type operator()(Args&&... args) {
        if(f != nullptr){
            (*f)(std::forward<Args>(args)...);
        }
        else
        {
            //DO Nothing for void 
        }
    }
};
//Usage:
WrapFuncObjVoid<foo> WrapFoo(&gfFoo);
WrapFoo();
WrapFuncObj<bar, int, char*> WrapBar(&gfBar); 
WrapBar(0, "test");

可以看到,非void和void类型需要单独的模板,因为在null的情况下,如果函数指针为null,则不应该返回任何内容。如何规避这个问题,使一个模板足够的两个?

您可以只使用return T();(假设T是您想要的返回类型)。这适用于void类型。它不适用于具有非默认构造函数的类型。

#include <iostream>
#include <utility>
void foo() {
    std::cout << "void foo()n";
}
 int bar(int u, char* c_str) {
    std::cout << "int bar(" << u << ", "" << c_str << "")n";
    return u;
 }
template<typename T>
class WrapFuncObj;
template<typename T,  typename... Args>
class WrapFuncObj<T(Args...)> {
    T (*f)(Args...);
public:
    WrapFuncObj(T (*t)(Args...)) {
        f = t;
    }
    T operator()(Args&&... args) {
        if(f != nullptr) {
            return (*f)(std::forward<Args>(args)...);
        } else {
            return T();
        }
    }
};
int main() {
    WrapFuncObj<void()> wrap_foo(&foo);
    wrap_foo();
    WrapFuncObj<int(int, char*)> wrap_bar(&bar); 
    wrap_bar(0, "test");
    WrapFuncObj<void()> wrap_null(nullptr);
    wrap_null(); // prints nothing.
}

现场演示。

我觉得有义务建议使用std::function,这是您试图重新发明的(除非您允许调用null函数并返回默认类型,这可能是也可能不是您真正想要做的事情)。