2012-01-19 129 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引用)。