我可以使用lambda函数或std :: function对象代替函数指针吗?

时间:2011-01-21 22:42:17

标签: c++ callback function-pointers lambda

我有一个我需要使用的库,它定义了以下内容:

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。

如果我能做些什么来澄清我的问题,请告诉我。在此先感谢您的帮助!

4 个答案:

答案 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>);