2011-11-07 84 views
2

我有這樣的模式:我可以製作具有相同簽名的String + lambda表嗎?

Thing * y = FindNearestItem(); 
if (y && (MenuElement * x = FindMenuElementNamed("Identity"))) 
    x->SetText(FString("%.1f", y)); 
else if (x) 
    x->Clear(); 
if (y && (MenuElement * x = FindMenuElementNamed("X1"))) 
    x->SetLocalData(y); 
else if (x) 
    x->Clear(); 

基本上,我想用一個靜態表: [警告:真的馬虎概念性代碼,無效的,我是一個小白,你已經被警告]:

struct Table { 
    const char * label; 
    ?lambda? lambda; 
} MyTable[] = { 
    "Identity", [] (const char * label, Thing * y) { MenuElement * x = FindMenuElementNamed(label); (y && x) ? x->SetText(FString("%.1f", y)) : x->Clear(); }, 
    "X1", [] (const char * label, Thing * y) { MenuElement * x = FindMenuElementNamed(label); (y && x) ? x->SetLocalData(y) : x->Clear(); }, 
}; 

Thing * y = FindNearestItem(); 
for (int i = 0; i != countof(MyTable); ++i) 
    MyTable[i].lambda(MyTable[i].label, y); 

請記住,每個標籤的動作都不相同 - 我的表中的每一行都是不同的。

所以模式大部分是一樣的,但方差在採取行動,雖然它在每種情況下使用相同的數據集(x,y,標籤)。但我不能簡單地調用x-> DoAppropriateThingFor(label,y);我只是回到創建一個長的基於標籤的if/else級聯...

隨意問我進一步的澄清。由於我還沒有機會真正使用它們,所以我在混合lambdas的黑暗中...

+0

我可以想到一些明顯的改進 - 比如將if!x條件放在lambda之外,因爲這是一個不變量。但是我需要知道是否追求這一點是有道理的。 :) – Mordachai

+0

我相信你會在這裏需要一個模板,因爲你不能聲明lambda類型的名稱IIRC – JaredPar

回答

5

只要所有的lambdas都是無捕獲的(即,[]是空的),您可以用一個函數指針:

struct Table { 
    const char* label; 
    void (*lambda)(const char*, Thing*); 
}; 

如果任何lambda表達式是有狀態(即[]不爲空),那麼你就不能使用函數指針。您可以使用std::function,雖然:

struct Table { 
    const char* label; 
    std::function<void(const char*, Thing*)> lambda; 
}; 

的Visual C++ 2010不支持拉姆達到函數指針的轉換(即轉換加入到Visual C++ 2010年被釋放後的語言),但在Visual C++ 11開發者預覽支持轉換。如果您使用的是Visual C++ 2010,則可以使用std::function解決方案。

+0

這將是一個鉸鏈,無論編譯器是否允許將lambda語法嵌入到表的靜態初始化列表中...... – Mordachai

+0

@Mordachai:我沒有再安裝Visual C++ 2010,但Visual C++ 11 Developer Preview在表格的靜態初始化程序中接受了這兩種方法。 –

+0

錯誤C2440:'initializing':無法從'匿名命名空間':: '轉換爲'void(__cdecl *)(ITEM *,CDynamicMenuItem *)' – Mordachai

相關問題