2012-01-19 115 views
2

我在vc2010上写了一些使用lambda的代码。代码的简化结构是象下面这样:使用嵌套lambda时出现奇怪的编译错误

template<typename Functor> 
bool f1(int a, Functor& f) 
{ 
    return f(a+1); 
} 

template<typename Functor> 
bool f2(Functor& f) 
{ 
    return f(1); 
} 

template<typename Functor> 
bool f3(Functor& f) 
{ 
    return f2([&](int a) -> bool { 
     // (1) Works 
     auto test = [&](int b) -> bool { return f(a+b); }; 
     return f1(a, test); 

     // (2) Doesn't work   
     //return f1(a, [&](int b) -> bool { return f(a+b); }); 
    }); 
}; 

int main() 
{ 
    int a = 100; 

    f3([&](int b) { return (a+b)%2 == 0; }); 
} 

首先我写一个嵌套拉姆达代码作为(2),和VC10给出像下面

'f1' : cannot convert parameter number from 'int' to 'int &' 

然而代码(1)的工作原理一个难以理解的错误消息那么,除了左值外,这与(2)是一致的。

我的问题是:

  1. 是代码(2)符合C++ 11标准?
  2. 如果不是,这种奇怪的编译行为是什么原因?

回答

4
return f1(a, [&](int b) -> bool { return f(a+b); }); 

在这里,它是一个lambda第二个参数,是不能被结合到非const引用临时对象。我相信,错误信息是误导性的;它并不完全说明问题。一个好的编译器会打印更好的错误信息。尝试GCC或Clang。

的修复程序是这样的:使第二个参数非参考:

template<typename Functor> 
bool f1(int a, Functor f) //I removed `&` from the second parameter 
{ 
    return f(a+1); 
} 

同样地,使所有在其他功能Functor参数非参考。传递函数作为参考没有多大意义,尤其是在C++ 11中,您可以在其中传递lambda以及您可以即时定义的lambda。

+1

哦,它帮了我很多。谢谢! – summerlight

4

GCC 4.6提供了以下错误:

a.cpp: In function ' int main() ':
a.cpp:30:43: error: no matching function for call to ' f3(main()::<lambda(int)>) '
a.cpp:30:43: note: candidate is:
a.cpp:14:6: note: bool f3(Functor&) [with Functor = main()::<lambda(int)> ]
a.cpp:14:6: note: no known conversion for argument 1 from ' main()::<lambda(int)> ' to ' main()::<lambda(int)>& '

哪个更清楚:你的lambda表达式是临时工,你试图将它们绑定到左值引用。所以只是使用r值参考或根本没有参考:

template<typename Functor> 
bool f1(int a, Functor&& f) 
{ 
    return f(a+1); 
} 

template<typename Functor> 
bool f2(Functor&& f) 
{ 
    return f(1); 
} 

template<typename Functor> 
bool f3(Functor&& f) 
{ 
    return f2([&](int a) -> bool { 
     // (1) Works 
     auto test = [&](int b) -> bool { return f(a+b); }; 
     return f1(a, test); 

     // (2) Doesn't work   
     //return f1(a, [&](int b) -> bool { return f(a+b); }); 
    }); 
}; 

int main() 
{ 
    int a = 100; 

    f3([&](int b) { return (a+b)%2 == 0; }); 
} 

不知道如果VS可以编译这个,但GCC做对了。

+0

或'const'引用。 –

0

正如其他人所说,你不能绑定一个临时的非const引用。

有3种方法来解决这个:

  1. 传值:

    模板 布尔F1(INT一个,函子F) { 返回F(A + 1); }

  2. 通由右值:

    模板 布尔F1(INT一个,函子& & F) { 返回F(A + 1); }

  3. 通由左值:

    模板 布尔F1(INT一个,常量函子& F) { 返回F(A + 1); }

我会去第三个选项(通过左值或const引用)。