3

我编写了一个event类模板,旨在提供 C# 风格的事件:事件实例存储为类的公共成员,以向所有者类提供不同的事件。例如:

template<typename SENDER , typename ARGS>
class event{ .... };

struct foo
{
    event<foo,int> event_a;
    ...

    void do_work()
    {
        int data;

        ....

        event_a.raise_event( *this , a );
    }
};

void on_event_a(foo& , int&) { std::cout << "On event_a of class foo!" << std::endl; }

struct bar
{
    void on_event_a(int&) { std::cout << "Catching an event with a member function!"; }
};


int main()
{
    int argumment;

    foo foo_instance;
    bar bar_instance;

    foo.event_a.add_handler( [](foo& , int& ) { std::cout << "Lambda!" << std::endl; } );
    foo.event_a.add_handler( on_event_a );
    foo.event_a.add_handler( bar_instance , &bar::on_event_a );

    foo_instance.do_work();
}

输出是:

拉姆达!
在 foo 类的 event_a 上!
使用成员函数捕捉事件!

现在我想使用该机制以 OO 样式包装 freeglut。具体来说,我不想编写一个类来负责管理不同的 freeglut 事件(窗口大小调整、键盘输入、鼠标移动等)。
我的第一个想法是使用类构造函数为每个 freeglut 回调注册一个 lambda,并且 lambda 绕过回调的参数到适当的事件,如下所示:

class freeglut_events
{
    event<freeglut_events> repaint_event;

    freeglut_events()
    {
        glutDisplayFunc( [&](){ repaint_event.raise_event( *this ); } );                
    }
};

但这会导致以下编译器错误(我使用的是 Visual Studio 2012):

没有从 '[]lambda() -> void' 到 'void(*)()' 的有效转换

我的理解是,注册函数期望的全局函数指针的签名和 lambda 的签名并不完全相等,因为 lambda 捕获本地数据。

我的问题是:有没有其他优雅的方式来实现这一目标?

4

1 回答 1

2

好吧,你不能那样做。因为只有非捕获的 lambda 可以转换为函数指针,并且glutDisplayFunc接受一个函数指针参数,即void (*func)(void).

另请参阅此答案:将 1 个参数(指针)传递给 glutDisplayFunc?

于 2013-10-12T22:12:10.640 回答