在类中包装freeglut回调的最优雅方法

时间:2013-10-12 21:28:00

标签: c++ visual-studio-2012 c++11 freeglut

我编写了一个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();
}

输出结果为:

  

LAMBDA!
  关于foo的event_a!
  使用成员函数捕获事件!

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

class freeglut_events
{
    event<freeglut_events> repaint_event;

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

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

  

'[] lambda() - &gt;没有有效转换void'to'void(*)()'

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

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

1 个答案:

答案 0 :(得分:2)

嗯,你做不到。因为只有非捕获的lambdas可以转换为函数指针,glutDisplayFunc采用函数指针参数,即void (*func)(void)

另请参阅此答案:Passing 1 argument (pointer) to glutDisplayFunc?