2017-04-21 30 views
1

我想聲明一個函數,它將具有特定原型的函數(或lambda)作爲參數。如何在C++中聲明對lambda的引用

的第一次嘗試是:

#include <iostream> 
using namespace std; 
int test(int (&val)(int)) { 
    return val(2); 
} 
int main() { 
    cout << test([](int v){ 
     return v+100; 
    }); 
    return 0; 
} 

error: invalid initialization of non-const reference of type 'int (&)(int)' from an rvalue of type 'main()::<lambda(int)>'

女巫結果我嘗試添加常量指定的類型,但我不知道確切位置,所以我試圖與海灣合作委員會工作的下面(-std = C++ 14),但我懷疑它是非法的,因爲它沒有鏗鏘:

int test(const auto& val) { 
    return val(2); 
} 

我知道我可以使用模板或函數指針或std ::功能實現相同,那麼請考慮這是一個教學問題。我想知道在上面的第二個例子(int test(const auto& val))中,GCC推導出什麼類型的val。通過lambda表達式產生

template <typename F> 
int test(F val) { 
    return val(2); 
} 

int test(int val(int)) { 
    return val(2); 
} 

int test(std::function<int(int)> val) { 
    return val(2); 
} 
+0

當然,他們建議使用模板或std :: function,但是使用GCC編譯器,即使沒有模板,它也能工作。 – biowep

+0

@cpplearner我認爲這是唯一可能的解釋,你應該發送一個答案。謝謝! – biowep

+0

[通過接受函數指針可以很好地工作](http://rextester.com/JPNGG21655)雖然無捕獲lambda轉換爲函數指針是隱式的,並且函數引用和函數指針之間的轉換也是隱含的,但將這些轉換鏈接在一起也是如此許多。 –

回答

1

I want to declare a function that takes as argument a function (or lambda) with a specific prototype.

閉包有一個唯一的和匿名類型。它們也可以是通用的(即模板operator()。沒有「簡單」的方式來聲明接受具有特定原型的lambdas的函數。您最好的選擇是使用std::is_invocable之類的約束模板參數或使用某種類型的擦除類型,如function_view

注意:如果您的lambda是無捕獲它可以隱式轉換爲函數指針。例如。

int test(int (*)(int)) { } 

test([](int) -> int {});  // OK 
test([i = 0](int) -> int {}); // compile-time error 

I want to know what does GCC deduce the type of val to, in the second example.

int test(int val(int)) 

...等價於...

int test(int (*val)(int)) 

事實上,在重新定義誤差範圍相同的結果有兩個人:

int test(int val(int)) { 
    return val(2); 
} 

int test(int (*val)(int)) { 
    return val(2); 
} 

prog.cc:5:5: error: redefinition of 'test' 
int test(int (*val)(int)) { 
    ^
prog.cc:1:5: note: previous definition is here 
int test(int val(int)) { 
    ^
+0

對不起,也許我沒有正確表達我自己,我的第二個例子是'int test(const auto&val)'。我沒有收到警告 – biowep

+2

@biowep,auto不能用在函數參數列表中。要採取任何類型,必須使用模板 - 模板 int test(const T&val)' – ralismark