2012-09-06 72 views
4

在GCC 4.5,下面的代码编译和与-std=c++0x预期工作,通过模板引用传递C++ 11拉姆达

#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"); })); 
} 

我没有我想我可以像这样做一个临时地址。也许这样解决了这个问题,尽管烦人的是要求函数的用户传递闭包的地址而不是方便的引用。

+2

使用'H && h'或'const H&'。 – 2012-09-06 17:07:21

+0

@Vlad:哦,嘿,那&''操作员工作。这在这方面意味着什么?不是“和”我猜。我从来没有见过'&&'那种用法。 – Steve

+0

@Steve'&&'是一个右值引用。 – ecatmur

回答

6

您试图通过非const引用传递临时值。这不适用于任何类型。

改为使用const引用传递lambda。

+0

谢谢。默认情况下不是lambdas'const'吗?或者至少是不变的。 – Steve

+0

@Steve默认,是的,但它们可以是'可变的'。 – ecatmur

+0

是的,它们默认是不可变的。但是这仍然意味着你必须明确地使用'const H&'。尽管我对指针解决方案感到好奇 - 在这种情况下,'H'等于'const TheLambdaType',以使'H *'为'const TheLambdaType *'? –