如何创建一个函数,它以任意函数指针作为参数?
How can you make a function that takes as a parameter an arbitrary function pointer?
我正在尝试执行以下操作,我什至不确定是否可行。
我想要一个接受任意函数指针并将其传递给不同函数的函数(我知道这是一种代码味道,良好的软件工程实践不是我现在想讨论的)。
换句话说,我正在寻找的东西看起来像:
void method1(arbitraty pointer p)
{
method2(p);
}
我不确定是否有办法声明任意函数指针(return 值保证为 void 但参数是任意的,无论是数量还是类型)
这可能被某些人认为是过度设计,但您可以尝试以下操作:
为您感兴趣的每个回调创建一个枚举:
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.
那你就可以写
template<GlfwCallback callback>
void method1(GlfwCallbackType<callback>::CallbackType p) {
// do something with p
method2<callback>(p);
};
另外请注意,您可以根据应用程序的需要向 "type family" 添加其他类型甚至静态函数和数据成员。
一种做你想做的事情的可能性,但以一种很好的、类型安全的方式,将是使用函子,即 class 为 operator()
定义重载的对象。
由于仿函数是 class,您可以将参数设置为数据成员,并将要作为任意指针传递的函数的 implementation/calling 移动到 operator() 方法中,您可以在其中拥有通过 this
指针访问所有参数。
此外,您可以定义一个函子层次结构,每个函子都有专门的参数和实现,因此您可以像下面这样修改 method2 的签名:
method2(BaseFunctor* myfunctor) {
if (myfunctor)
(*myfucntor)();
}
并在调用上下文中设置正确类型的仿函数对象。
另请查看 lambdas (c++11),它基本上是函子定义的快捷方式。
仅当推导的类型是函数指针类型时,使用模板并使用 SFINAE 启用它:
template <typename T, std::enable_if_t<std::is_function<T>::value, int> = 0>
void method1(T* p)
{
// ...
}
我正在尝试执行以下操作,我什至不确定是否可行。
我想要一个接受任意函数指针并将其传递给不同函数的函数(我知道这是一种代码味道,良好的软件工程实践不是我现在想讨论的)。
换句话说,我正在寻找的东西看起来像:
void method1(arbitraty pointer p)
{
method2(p);
}
我不确定是否有办法声明任意函数指针(return 值保证为 void 但参数是任意的,无论是数量还是类型)
这可能被某些人认为是过度设计,但您可以尝试以下操作:
为您感兴趣的每个回调创建一个枚举:
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.
那你就可以写
template<GlfwCallback callback>
void method1(GlfwCallbackType<callback>::CallbackType p) {
// do something with p
method2<callback>(p);
};
另外请注意,您可以根据应用程序的需要向 "type family" 添加其他类型甚至静态函数和数据成员。
一种做你想做的事情的可能性,但以一种很好的、类型安全的方式,将是使用函子,即 class 为 operator()
定义重载的对象。
由于仿函数是 class,您可以将参数设置为数据成员,并将要作为任意指针传递的函数的 implementation/calling 移动到 operator() 方法中,您可以在其中拥有通过 this
指针访问所有参数。
此外,您可以定义一个函子层次结构,每个函子都有专门的参数和实现,因此您可以像下面这样修改 method2 的签名:
method2(BaseFunctor* myfunctor) {
if (myfunctor)
(*myfucntor)();
}
并在调用上下文中设置正确类型的仿函数对象。
另请查看 lambdas (c++11),它基本上是函子定义的快捷方式。
仅当推导的类型是函数指针类型时,使用模板并使用 SFINAE 启用它:
template <typename T, std::enable_if_t<std::is_function<T>::value, int> = 0>
void method1(T* p)
{
// ...
}