我有一个我需要使用的库,它定义了以下内容:
typedef void CallbackFunction(const int& i);
并具有注册回调的功能,如下所示:
void registerCallback(CallbackFunction* pCallback);
因为我想捕获要在回调中使用的几个变量的状态,所以我不能简单地使用普通函数。我更喜欢使用的是lambda函数,但以下内容不能编译:
auto fCallback = [](const int& i) {
cout << i << endl;
};
registerCallback(fCallback);
而是我得到错误:
error C2664: 'registerCallback' : cannot convert parameter 1 from '`anonymous-namespace'::<lambda0>' to 'CallbackFunction (__cdecl *)'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
我一直在阅读这个主题很多,并尝试了一些不同的(可能是愚蠢的)方法,但我似乎无法让这个工作。转换函数允许代码编译,但(毫不奇怪)它崩溃了。可能是我在StackOverflow或其他地方忽略了解决方案,所以链接就足够了。 (虽然,由于我对其中的一些技术有点新,请确保新手的通信清晰。例如,如果this conversation包含我的答案,我不明白。请简化或解释通信。)仅供参考,我正在使用Visual C ++ 2010。
如果我能做些什么来澄清我的问题,请告诉我。在此先感谢您的帮助!
答案 0 :(得分:8)
通常,不能使用需要函数指针的lambda或函数对象。函数对象是已经过载应用程序运算符(()
)的完整对象,因此您可以在语法上将它们用作函数。
标准算法作为模板编写,允许您将函数地址(指针)或函数对象传递给它们,因为它们使用相同的语法。传递函数对象时,会实例化一个接受该函数对象的模板;当您传递函数指针时,将实例化另一个模板。
因此,要使lambda / function对象与代码一起使用,您需要修改正在使用的库。
答案 1 :(得分:7)
由于你没有捕获任何东西,你应该能够做你想要做的事情,即将lambda表达式指定为函数指针(尽管你的语法错误)。
既然你正在使用VS2010,那么你将无法做到。你试图使用的lambda的特性直到VS2010发布后才出现:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3043.html
所以,虽然是的,它应该可以实现它实际上没有。
当然,实际上,虽然你不是在捕捉任何你想做的事情。即使在C ++草案标准的VS2010后状态下,捕获数据的Lambda也无法转换为函数指针。
答案 2 :(得分:4)
Lamda只是算子的语法糖 函数是像函数一样运作的对象。
函数指针不是同一类型的东西。通常,您不能在需要函数指针的地方使用仿函数。
另一方面,很容易将函数包装成一个函子。
函数指针通常由C库使用。由于C ++库将使用一个接口来实现相同的效果。因此,您可以看到为什么很难传递函数指针需要的仿函数(C代码无法理解如何使用仿函数)。
答案 3 :(得分:0)
您不能使用lambdas,因为您的registerCallback
函数需要指向非成员函数的指针。将附加参数传递给自由站立功能的唯一方法是1)使用全局(静态)数据或2)使其成为采用编译时常数的模板,例如
template<int data> void callback(const int& i)
{ /* can use data */ }
registerCallback(callback<10>);