2010-05-30 32 views
53

我在網上閱讀了很多教程,解釋瞭如何使用帶有標準庫的lambda表達式(例如std::find),它們都非常有趣,但是我找不到解釋如何使用lambda表示我自己的lambda表達式功能。如何聲明一個接受lambda的函數?

例如:

int main() 
{ 
    int test = 5; 
    LambdaTest([&](int a) { test += a; }); 

    return EXIT_SUCCESS; 
} 

我應該怎樣申報LambdaTest?第一個參數的類型是什麼?然後,我該如何調用傳遞給它的匿名函數 - 例如 - 「10」作爲它的參數?

回答

51

鑑於您可能還希望接受函數指針和函數對象以及lambda函數,您可能需要使用模板來接受任何參數與operator()。這就是find的std函數的作用。它看起來像這樣:

template<typename Func> 
void LambdaTest(Func f) { 
    f(10); 
} 

請注意,此定義不使用任何C++ 0x功能,因此它完全向後兼容。這只是使用lambda表達式對C++ 0x特定的函數的調用。

+0

這是最好的答案。 – Puppy 2010-05-30 12:39:04

+2

如果出現錯誤,錯誤消息將難以理解。 – liori 2010-05-30 12:40:57

+13

這取決於它是否最好。這使用了一個模板,而另一個沒有。這意味着該函數不能再是虛擬的,並且不能在cpp文件中單獨定義。 'std :: function'完全能夠使用函數對象類類型,儘管調用時會稍微慢一些。但是這種差別對於大多數應用程序來說是微不足道的:) – 2010-05-30 12:41:15

53

如果你不想模板的一切,你可以做到以下幾點:

void LambdaTest (const std::function <void (int)>& f) 
{ 
    ... 
} 
+1

這個語法實際上允許我保存函數變量以後再調用它,對吧?例如,我想實現一個允許執行異步數據庫查詢的函數,其中lambda充當回調函數。 (當然,我不能通過引用訪問閉包) – 2010-05-30 12:52:07

+1

按價值傳遞函數不是更習慣嗎? – fredoverflow 2010-05-30 12:53:04

+1

@Andreas Bonini:是的,如果你保存到'std :: function'(不是引用),你會複製'f'。然而,我不確定當引用的對象超出範圍時,lambda/closures如何處理引用,可能是UB。 @FredOverflow:我的理解是'std :: function'不是一個簡單的對象,特別是在包裝lambda時。引用它可能會更好,以避免不必要的複製。 – doublep 2010-05-30 13:01:15

4

我想貢獻這個簡單但不言自明的例子。它展示瞭如何將「可調用事物」(函數,函數對象和lambda表達式)傳遞給函數或對象。

// g++ -std=c++11 thisFile.cpp 

#include <iostream> 
#include <thread> 

using namespace std; 

// ----------------------------------------------------------------- 
class Box { 
public: 
    function<void(string)> theFunction; 
    bool funValid; 

    Box() : funValid (false) { } 

    void setFun (function<void(string)> f) { 
    theFunction = f; 
    funValid = true; 
    } 

    void callIt() { 
    if (! funValid) return; 
    theFunction (" hello from Box "); 
    } 
}; // class 

// ----------------------------------------------------------------- 
class FunClass { 
public: 
    string msg; 
    FunClass (string m) : msg (m) { } 
    void operator() (string s) { 
    cout << msg << s << endl; 
    } 
}; 

// ----------------------------------------------------------------- 
void f (string s) { 
    cout << s << endl; 
} //() 

// ----------------------------------------------------------------- 
void call_it (void (*pf) (string)) { 
    pf("call_it: hello"); 
} //() 

// ----------------------------------------------------------------- 
void call_it1 (function<void(string)> pf) { 
    pf("call_it1: hello"); 
} //() 

// ----------------------------------------------------------------- 
int main() { 

    int a = 1234; 

    FunClass fc (" christmas "); 

    f("hello"); 

    call_it (f); 

    call_it1 (f); 

    // conversion ERROR: call_it ([&] (string s) -> void { cout << s << a << endl; }); 

    call_it1 ([&] (string s) -> void { cout << s << a << endl; }); 

    Box ca; 

    ca.callIt(); 

    ca.setFun (f); 

    ca.callIt(); 

    ca.setFun ([&] (string s) -> void { cout << s << a << endl; }); 

    ca.callIt(); 

    ca.setFun (fc); 

    ca.callIt(); 

} //() 
+2

中傳遞。您不需要funValid:http://en.cppreference.com/w/cpp/utility/functional/function/operator_bool,只要說'if(!theFunction)' – 2017-01-20 19:32:30

相關問題