2014-02-21 71 views
0

C++ 11沒有捕獲任何東西的lambda表達式可以存儲在函數指針中。只需要確保lambda接受並返回與函數指針相同的參數。使用C++ 11 lambda作爲GObject庫中的回調函數

GObject庫中,所有回調的類型爲void(*GCallback) (void)。儘管此定義並不影響回調的簽名,但是:

用於結構定義中的回調函數的類型和函數簽名的 函數簽名。這並不意味着所有回調函數 都不能使用參數並返回void。回調函數所需的簽名由所使用的上下文(例如,其連接的信號爲 )確定。使用G_CALLBACK()將 回調函數強制轉換爲GCallback。

換句話說,一個可以傳遞函數是這樣的:鑄造它的類型

int my_function(int a, char b) {} 

(這就是G_CALLBACK做):

do_something(G_CALLBACK(my_function)); 

不幸的是鑄字不使用C +工作+11 lambda:

do_something(G_CALLBACK([](int a, char b) -> int {...}); 
// Cannot cast from type lambda to pointer type GCallback 

是否有可能使用任意類型的C++ lambda來代替GCallback?

UPDATE

只是爲了澄清,我知道拉姆達可以澆鑄爲函數指針,如果他們的簽名匹配。我的問題在另一個方面。

ISO C標準保證了功能可以在不失去任何精度的前提下返回。換言之一個下面的表達式是有效的:

int f(int a){...} 

void (*void_f)() = (void (*)())f; 
int (*restored_f)(int) = (int (*)(int))void_f; 
restored_f(10); 

我的問題是下面的表達式是否也是有效根據C++ 11:

int (*f)(int) = [](int a) -> int {}; 
void (*void_f)() = (void (*)())f; 
int (*restored_f)(int) = (int (*)(int))void_f; 
restored_f(10); 
+0

我還沒有嘗試過自己,但你可以嘗試將拉姆達存儲爲一個變量('自動樂趣= []( ...){...};'),然後在'do_something'調用('do_something(reinterpret_cast (fun));')中做明確的轉換。由於我沒有嘗試過,所以我不知道它是否會起作用。 –

+2

http://stackoverflow.com/questions/15657011/is-it-safe-to-cast-a-lambda-function-to-a-function-pointer – SomeWittyUsername

+0

@icepack這個問題不是關於如何使用lambdas到位的函數指針。這是關於如何(如果可能)使用任意類型的lambda來代替GCallback。 – Kentzo

回答

0

lambda表達式沒有捕獲are implicitly convertible的指針標準的功能。儘管目前並非所有編譯器都支持此功能(https://stackoverflow.com/a/2935230/261217)。

然後你可以顯式地將一個函數指針轉到GCallback

+0

請看我的問題的更新。第二個表達式在C++ 11下是否有效?如果是這樣,你能指出標準嗎? – Kentzo

+0

我看到這個轉換沒有問題,lambda函數只是匿名類的一個方法。它就像普通函數一樣存在。雖然我不能指向標準,對不起,我太懶惰了:) – Mikhail

0

下面的代碼編譯和我的作品(MSVC 2013):

auto lambdaFunc = [](int a, char b) -> int { return 0; }; 

typedef int (*LambdaType)(int, char); 

GCallback fnTest1 = G_CALLBACK((LambdaType)lambdaFunc); 
GCallback fnTest2 = G_CALLBACK((LambdaType) [](int a, char b) -> int { return 0; }); 

do_something(fnTest1); 
do_something(fnTest2); 
do_something(G_CALLBACK((LambdaType)lambdaFunc));