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

发布于 2024-10-13 12:21:10 字数 1084 浏览 3 评论 0原文

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

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 或其他地方的解决方案,因此一个链接就足够了。 (不过,由于我对其中一些技术有点陌生,请确保对于新手来说对应关系足够清晰。例如,如果 此对话包含我的答案,我不明白。请简化或解释对应关系。)仅供参考,我正在使用 Visual C++ 2010 。

如果我可以做些什么来澄清我的问题,请告诉我 预先感谢您的帮助!

I've got a library that I need to use that defines the following:

typedef void CallbackFunction(const int& i);

and has a function to register your callback that looks like:

void registerCallback(CallbackFunction* pCallback);

Because I'd like to capture the state of several variables to be used in the callback, I can't simply use a plain function. What I'd prefer to use is a lambda function, but the following doesn't compile:

auto fCallback = [](const int& i) {
    cout << i << endl;
};
registerCallback(fCallback);

instead I get the error:

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

I've been reading up on this topic a lot, and trying a few different (probably idiotic) approaches, but I can't seem to get this to work. Casting the function allows the code to compile, but (not surprisingly) it crashes. It may be that I've overlooked the solution either here on StackOverflow or elsewhere, so a link will suffice. (Though, since I'm a bit new to some of these techniques, please make sure that the correspondence is clear enough for a newbie. For instance, if this conversation contains my answer, I don't understand. Please simplify or explain the correspondence.) FYI, I'm using Visual C++ 2010.

Please let me know if there is anything I can do to clarify my question. Thanks in advance for the help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

像你 2024-10-20 12:21:10

一般来说,不能在需要函数指针的地方使用 lambda 或函数对象。函数对象是成熟的对象,已重载应用程序运算符 (()),因此您可以在语法上将它们用作函数。

标准算法被编写为模板,这允许您向它们传递函数地址(指针)或函数对象,因为它们使用相同的语法。当您传递一个函数对象时,会实例化一个接受该函数对象的模板;当您传递函数指针时,会实例化一个不同的模板。

因此,要让 lambda/函数对象与您的代码配合使用,您需要修改您正在使用的库。

In general, no you can't use a lambda or function object where a function pointer is required. Function objects are full-fledged objects that have overloaded the application operator (()) so you can use them as functions syntactically.

The standard algorithms are written as templates, which allows you to pass either a function address (pointer) or a function object to them, because they use the same syntax. When you pass a function object, a template is instantiated which accepts that function object; when you pass a function pointer, a different template is instantiated.

So to get lambdas/function objects to work with your code, you would need to modify the library you're using.

对风讲故事 2024-10-20 12:21:10

由于您没有捕获任何内容,因此您应该能够执行您想要执行的操作,即将 lambda 表达式指定为函数指针(尽管您的语法在那里是错误的)。

但由于您使用的是 VS2010,因此您将无法这样做。您尝试使用的 lambda 功能直到 VS2010 发布后才出现: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3043.html

所以虽然是的,但它应该可以工作事实上并非如此。

当然,事实上,虽然您没有捕获任何您声称想要捕获的东西。即使在 C++ 草案标准的 VS2010 后状态下,捕获数据的 Lambda 也无法转换为函数指针。

Since you capture nothing, you are supposed to be able to do what you're trying to do, namely assign a lambda expression as a function pointer (though your syntax is wrong there).

Since you're using VS2010 though, you won't be able to. The feature of lambda that you're trying to use did not come to be until after VS2010 was released: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3043.html

So while yes, it's supposed to work it in fact does not.

Of course, while you are not, in fact, capturing anything you do state that you want to. Lambdas that capture data cannot be converted to function pointers even in the post VS2010 state of the C++ draft standard.

暖心男生 2024-10-20 12:21:10

简短回答:没有

长回答:

Lamda 只是函子的语法糖。
函子是行为类似于函数的对象。

函数指针不是同一类型的东西。一般来说,在需要函数指针的地方不能使用函子。

额外:

另一方面,将函数包装为函子很容易。

从历史上看:

函数指针通常由 C 库使用。正如C++库将使用接口来实现相同的效果。因此,您可以明白为什么在需要函数指针的地方传递函子很困难(C 代码无法理解如何使用函子)。

Short Answer: No

Long Answer:

Lamda's are just syntactic sugar for functors.
Functors are objects that act like functions.

A function pointer is not the same type of thing. In general you can not use functors where you need a function pointer.

Extra:

On the other hand it is easy to wrap a function to become a functor.

Historically:

Function pointers are generally used by C libraries. As C++ libraries will use an interface to achieve the same affect. Thus you can see why it is hard to pass functors where a function pointer is requried (the C code has no way to understand how to use the functor).

小红帽 2024-10-20 12:21:10

您不能使用 lambda,因为您的 registerCallback 函数需要指向非成员函数的指针。将附加参数传递给独立函数的唯一方法是 1)使用全局(静态)数据或 2)使其成为采用编译时常量的模板,例如

template<int data> void callback(const int& i)
{ /* can use data */ }

registerCallback(callback<10>);

You can't use lambdas, because your registerCallback function expects pointer to non-member function. The only way to pass additional parameter to free standing function is 1) using global (static) data or 2) making it a template taking compile time constants, e.g.

template<int data> void callback(const int& i)
{ /* can use data */ }

registerCallback(callback<10>);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文