C ++:闭包传递成员函数作为普通函数指针 [英] C++: closure to pass member function as normal function pointer

查看:287
本文介绍了C ++:闭包传递成员函数作为普通函数指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 计时器。我试图调用一个外部库的成员函数,它接受一个函数指针作为参数。 :: every(unsigned long period,void(* callback)(void)); 

但是不幸的是我想传递的参数是一个成员函数:

  void MyClass :: the_method_i_want_to_pass(void); 

由于我在Arduino(AVR)下为ATMega编程,所以只支持c + +11。我的第一个方法引发一个类型错误:

  void MyClass :: the_method_i_want_to_pass(){...} 

MyClass :: MyClass(){
// constructor

Timer * timer = new Timer();
timer-> every(500,[this](){this-> the_method_i_want_to_pass();})
}

编译器输出:


警告:警告:lambda表达式仅适用于-std = c ++ 11或-std = gnu ++ 11 [默认启用]



错误:没有匹配的函数调用'Timer :: every(int,MyClass :: MyClass():: __ lambda0)'





  1. 是否有其他/更好的解决方案?

  2. 关于我目前的方法:(如何)当需要函数指针时,可以传递一个lambda的引用?

  3. 如何知道Arduino / AVR支持这些lambdas(参见警告)?


解决方案

code> Timer 库是poorky写的:它应该至少 void(*)(void *),void * / p>

如果没有pvoid或等效项,您不能传递执行代码中的地址以外的任何状态,以运行过程。作为一种方法,还会返回一个这个指针,你是运气不好。



现在,如果你的实例 MyClass 是一个单例,你可以从别的地方获得 this



如果没有,你需要使你自己的全局状态,让你从一个特定的回调映射到一些状态。如果你有有限数量的 MyClass Timer 的其他消费者,你可以有一些固定的功能,他们在全球存储他们额外的状态。



这是一个黑客。下面是更糟。



编写一个具有全局状态和 void()接口的动态库。当你添加一个回调,复制动态库,在运行时修改它的全局状态,写出一个不同命名的库,加载它,并传递纯回调函数到你的 Timer class。



或者通过手动编写机器代码和将页面标记为可执行来实现没有库的公平。



<这些都是差的解决方案。这导致我一个好的:找到一个更好的计时器。如果他们搞砸了一些简单的东西,图书馆的其余部分也可能是坏的。


I'm trying to call a member function of an external library which takes a function pointer as a parameter:

Timer::every(unsigned long period, void (*callback)(void));

But unfortunately the parameter I want to pass is a member function:

void MyClass::the_method_i_want_to_pass(void);

Since I'm programming for the ATMega under Arduino (AVR) there is just limited support of c++11. My first approach raises a type error:

void MyClass::the_method_i_want_to_pass() {...}

MyClass::MyClass() {
    // constructor

    Timer *timer = new Timer();
    timer->every(500, [this](){this->the_method_i_want_to_pass();})
}

Compiler Output:

warning: warning: lambda expressions only available with -std=c++11 or -std=gnu++11 [enabled by default]

error: no matching function for call to ‘Timer::every(int, MyClass::MyClass()::__lambda0)’

  1. Are there other/better solutions?
  2. Concerning my current approach: (How) is it possible to pass a reference to a lambda when a function pointer is required?
  3. How can I find out if Arduino/AVR supports these lambdas (see "warning")?

解决方案

Your basic problem is your Timer library is poorky written: it should take void(*)(void*), void* at the least.

Without a pvoid or equivalent, you cannot pass any state other than the address in execution code to run the procedure at. As a method also rewuires a this pointer, you are out of luck.

Now, if your instance of MyClass is a singleton, you can get this from somewhere else.

Failing that, you need to make your own global state that lets you map from a particular callback to some state. If you have a limited number of MyClass and other consumers of Timer, you can have a few fixed functiins, and have them store their extra state globally.

This is all a hack. What follows is worse.

Write a dynamic library with some global state, and a void() interface. When you add a callback, duplicate that dynamic library, modify its global state at runtime, write it out as a differently named library, load it, and pass the pure callback function to your Timer class.

Or do the equvalent without a library by manually writing machine code and marking pages as execuable.

These are all poor solutions. Which leads me to a good one: find a better Timer. If they screwed up something that simple, the rest of the library is probably bad as well.

这篇关于C ++:闭包传递成员函数作为普通函数指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆