如何将函子分配给函数指针?

2023-12-26

一般来说,我可以将函数对象分配给函数指针吗?我想做这样的事情:

#include <iostream>

class Foo {
    int num;
public:
    Foo(int num_par) : num(num_par) {}
    void operator()(int multiplier) {
        std::cout << multiplier * num << std::endl;
    }
};

int main() {
    typedef void(*bar)(int);
    Foo f(42);
    bar b = f; // MSVC error
               // ^ C2440: 'initializing' : cannot convert from 'Foo' to 'bar'
    b(2); // wanted to print 84
}

如果那不可能,我想要一个专门用于 Windows 编程的替代方案,我想要的WindowProc包含从本地数据设置到的状态信息WinMain的主体(即不创建全局变量)。当分配给WNDCLASSEX’s lpfnWndProc成员。尽管std::function解决了上面代码片段的问题:

std::function<void(int)> sf = f;
sf(2); // prints 84

它不适用于我的 WinAPI 案例:

class WindowProc {
    int some_state;
public:
    void set_some_state(int par);
    LRESULT CALLBACK operator()(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
};

int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow) {

    HWND hWnd;
    WNDCLASSEX wc;
    WindowProc wp;

    typedef LRESULT(CALLBACK *baz)(HWND, UINT, WPARAM, LPARAM);

    std::function<baz> std_func = wp;
    std::function<baz> std_binded_func = std::bind(&WindowProc::operator(), &wp);

    // none of these compile:
    wc.lpfnWndProc = wp;                      // #1
    wc.lpfnWndProc = wp.operator();           // #2
    wc.lpfnWndProc = &WindowProc::operator(); // #3. Wrong anyway because some_state's value is part of the instance, not the class
    wc.lpfnWndProc = std_func;                // #4. Wrong anyway because some_state's value is part of the instance, not the class
    wc.lpfnWndProc = std_binded_func;         // #5

    // do stuff...
    wp.set_some_state(some_runtime_number);
    // ...do other stuff
}

MSVC 2013 错误:

1.) 错误 C2440:=: 无法转换自WindowProc to WNDPROC

2.) 错误 C3867:WindowProc::operator ():函数调用缺少参数列表;使用&WindowProc::operator ()创建指向成员的指针

2 续)错误 C2440:=: 无法转换自LRESULT (__stdcall WindowProc::* )(HWND,UINT,WPARAM,LPARAM) to WNDPROC

3.) 与“2 续”相同

4.) 错误 C2440:=: 无法转换自std::function<baz> to WNDPROC

5.) 与 4 相同。

我怎样才能让它发挥作用?


一般来说,函数对象除了要调用的函数之外还包含附加的上下文信息。唯一可以分配给函数指针的函数对象是带有空捕获的 lambda 函数,但这实际上只是一个函数:

void (*bar)(int) = [](int x) { std::cout << x; }

如果你想通过函数指针获取函数对象,你需要希望函数指针有一个合适的参数可供用户指定并且可以直接传递:

void call_function(int arg, void* user_data) {
    (*static_cast<std::function<void(int)>*>(userdata))(arg);
}
...

std::function<void(int)> function_object;
void (*bar)(int, void*) = &call_function;

bar(17, &function_object);

大多数采用函数指针的现代接口也采用用户数据指针,该指针可用于传递必要的上下文。显然,除了传递必要的上下文之外,可能还需要以某种方式维护用作上下文的对象的生命周期。

我不是 Windows 程序员,但我猜测您尝试使用的 API 实际上能够设置函数指针和指向某些用户数据的指针。如果没有地方可以传递上下文信息,则需要以某种方式在函数指针本身中对必要的信息进行编码。例如,您可以使用引用全局对象的函数指针来获取上下文。显然,对于要传递的每个上下文,您需要一个不同的函数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将函子分配给函数指针? 的相关文章

随机推荐