如何创建一个将任意函数指针作为参数的函数?

时间:2018-04-15 03:28:28

标签: c++ pointers function-pointers

我正在尝试做以下事情,我甚至不确定是否可能。

我想要一个函数,它接受一个任意函数指针将它传递给另一个函数(我知道这是代码味道,良好的软件工程实践不是我现在想要讨论的内容)。

换句话说,我想要的是:

void method1(arbitraty pointer p)
{
    method2(p);
}

我不确定是否有办法声明任意函数指针(返回值保证为void但参数是任意的,无论是数量还是类型)​​

3 个答案:

答案 0 :(得分:3)

使用模板并仅在推断的类型是函数指针类型时使用SFINAE才能启用它:

template <typename T, std::enable_if_t<std::is_function<T>::value, int> = 0>
void method1(T* p)
{
    // ...
}

答案 1 :(得分:1)

某些人可能会认为这可能会过度工程,但您可以尝试以下方法:

创建您感兴趣的每个回调的枚举:

["h","e","l","l","o"].forEach(function(e){
    var k = ["w","o","r","l","d"]
    var i = 0
    do 
      k[i] = e+k[i],i++
    while (i < k.length)
    console.log(k)
    })

然后创建一个类型系列,将其中的每一个与相应的函数指针类型相关联。通过创建模板结构并反复对其进行专门化来完成此操作:

enum GlfwCallback {
    KeyCallback,
    FramebufferSizeCallback,
    // etc.
};

然后你可以写

template<GflwCallback callback>
struct GlfwCallbackType {};

template<>
struct GlfwCallbackType<KeyCallback> {
    using CallbackType = GLFWkeyfun;
    // or
    using CallbackType = void(*)(GLFWwindow *, int, int, int, int);
};

template<>
struct GlfwCallbackType<FramebufferSizeCallback> {
    using CallbackType =  GLFWframebuffersizefun;
};

// etc.

另请注意,您可以根据应用程序的需要将其他类型甚至静态函数和数据成员添加到“类型系列”。

答案 2 :(得分:1)

有可能做你想要的,但是以一种漂亮的,类型安全的方式,可以使用仿函数,即定义operator()的重载的类。
由于仿函数是一个类,您可以将参数设置为数据成员,并将要作为任意指针传递的函数的实现/调用移动到operator()方法中,您可以通过该方法访问所有参数this指针。

此外,您可以定义仿函数的层次结构,每个仿函数都有专门的参数和实现,因此您可以修改method2的签名,如下所示:

method2(BaseFunctor* myfunctor) {
   if (myfunctor) 
      (*myfucntor)();
} 

并在调用上下文中设置正确类型的仿函数对象。

另请查看lambdas(c ++ 11),它基本上是函子定义的快捷方式。