【发布时间】:2023-04-07 21:37:02
【问题描述】:
在 gcc 4.5 中,以下代码编译并按预期使用 -std=c++0x,
#include <stdio.h>
template<typename H>
void caller(H h)
{
h();
}
int main()
{
auto c = [](){ printf("A\n"); };
caller(c);
caller([](){ printf("B\n"); });
return 0;
}
打印,
A
B
但是,如果 caller 被定义为获取引用,
template<typename H>
void caller(H &h)
{
h();
}
编译器抱怨,
test.cpp: In function ‘int main()’:
test.cpp:61:34: error: no matching function for call to ‘caller(main()::<lambda()>)’
test.cpp:52:6: note: candidate is: void caller(H&) [with H = main()::<lambda()>]
为什么?
这似乎打破了 lambdas 为函数提供值语义的想法,但这意味着我不能内联编写某些小函数,这有点烦人。
(这在较新版本的 gcc 中是否已修复?我还没有机会测试。)
编辑:我刚刚发现以下实际可行:
template<typename H>
void caller(H *h)
{
(*h)();
}
int main()
{
auto c = [](){ printf("A\n"); };
caller(&c);
caller(&([](){ printf("B\n"); }));
}
我不认为我能得到这样的临时地址。也许这样可以解决问题,尽管要求函数的用户传入闭包的地址而不是方便的引用很烦人。
【问题讨论】:
-
@Vlad:哦,嘿,那个
&&操作员工作了。在这种情况下这意味着什么?我猜不是“和”。我从没见过&&这样用过。 -
@Steve
&&是一个右值引用。 -
嗯。学习新事物。谢谢!
-
您使用指针的第二个示例是一个错误。 GCC 4.7.1 fails 编译它。编辑:VS2010 也允许它,但是如果你将警告调高到 4 级,你会得到:warning C4238: nonstandard extension used : class rvalue used as lvalue
-
在问题的最后,您说您能够获取临时 lambda 的地址。你能告诉我们更多吗。 g++ 将通过
-f permissive警告允许这样做 - 这是你做的吗?