C++ 通过C&x2B+;11通过模板参考的λ

C++ 通过C&x2B+;11通过模板参考的λ,c++,lambda,c++11,C++,Lambda,C++11,在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; } 但是,如果调用方被定义为引

在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;
}
但是,如果
调用方
被定义为引用

template<typename H>
void caller(H &h)
{
    h();
}
模板
无效呼叫方(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()>]
test.cpp:在函数“int main()”中:
test.cpp:61:34:错误:调用“caller(main():)”时没有匹配的函数
test.cpp:52:6:注意:候选者是:void调用者(H&)[带H=main():]
为什么?

这似乎打破了lambdas为函数提供值语义的想法,但这意味着我无法内联编写某些小函数,这有点烦人

(这在新版本的gcc中是固定的吗?我还没有机会测试。)

编辑:我刚刚发现以下方法确实有效:

template<typename H>
void caller(H *h)
{
    (*h)();
}

int main()
{
    auto c = [](){ printf("A\n"); };
    caller(&c);
    caller(&([](){ printf("B\n"); }));
}
模板
无效调用方(H*H)
{
(*h)();
}
int main()
{
自动c=[](){printf(“A\n”);};
呼叫者&c;
调用方(&([]){printf(“B\n”);});
}

我没想到我能拿到这样一个临时工的地址。也许这样就解决了问题,尽管要求函数用户传递闭包地址而不是方便的引用很烦人。

您正在尝试通过非常量传递临时引用。这对任何类型都不起作用


改为通过常量引用传递lambda。

@Vlad:哦,嘿,
&
操作符工作了。在这种情况下,这意味着什么?我想不是“和”。我从来没有见过
&&
那样使用。@Steve
&&&
是一个右值引用。学习新事物。谢谢第二个使用指针的示例是一个bug。GCC 4.7.1,以编制该文件。编辑:VS2010也允许这样做,但如果您将警告调到第4级,您将从以下位置获得此信息:警告C4238:使用的非标准扩展:类rvalue用作左值在问题的末尾,您说您可以获取临时lambda的地址。你能告诉我们更多吗。g++将允许使用
-f permissive
警告-这是您所做的吗?谢谢。lambdas
const不是默认值吗?或者至少是不可变的。@Steve默认情况下是的,但它们可以是可变的。
是的,默认情况下是不可变的。但这仍然意味着您必须显式地使用
const H&
。不过,我对指针的解决方案很好奇——在这种情况下,
H
等于
const TheLambdaType
,以便
H*
be
const TheLambdaType*
?@AaronMcDaid,正如Prætorian所说,获取临时地址是非法的。
template<typename H>
void caller(H *h)
{
    (*h)();
}

int main()
{
    auto c = [](){ printf("A\n"); };
    caller(&c);
    caller(&([](){ printf("B\n"); }));
}