2010-07-23 96 views
17

請看看下面的C++ 0x的λ相關代碼:C++ 0x lambda,我怎樣才能作爲參數傳遞?

typedef uint64_t (*WEIGHT_FUNC)(void* param); 
typedef std::map<std::string, WEIGHT_FUNC> CallbackTable; 

CallbackTable table; 
table["rand_weight"] = [](void* param) -> uint64_t 
{ 
    return (rand() % 100 + 1); 
}; 

我得到一個錯誤(在Visual Studio 2010),該拉姆達不能轉換爲WEIGHT_FUNC類型。我也知道了答案:用std::function object

typedef std::function<uint64_t (void*)> WEIGHT_FUNC; 

不過,我也想知道我怎麼能接受的λ的類型,除非使用std::function。它應該是什麼類型?

+1

'auto'? auto_ – kennytm 2010-07-23 18:39:38

+2

auto只是用於自動確定類型,它不是變體類型,它不能是參數。 – Klaim 2010-07-23 18:41:36

+2

您正在使用哪種編譯器?似乎你的編譯器對於lambda來說是非標準的,它們應該能夠隱式地轉換成函數指針(在這種情況下) – GManNickG 2010-07-23 19:03:50

回答

20

爲一個函數指針的轉化是相對較新的:將其用N3043 2月15日推出,2010年

雖然例如GCC 4.5實現它,Visual Studio 10於2010年4月12日發佈,因此沒有及時實施。正如詹姆斯指出的,在未來的版本中這個will be fixed

目前,您必須使用此處提供的替代解決方案之一。

技術上類似如下的解決方法將工作,但沒有可變參數模板它不好玩來概括它(Boost.PP救援......),並沒有針對通過捕獲lambda表達式沒有安全網:

typedef uint64_t (*WeightFunc)(void* param); 

template<class Func> WeightFunc make_function_pointer(Func& f) { 
    return lambda_wrapper<Func>::get_function_pointer(f); 
} 

template<class F> class lambda_wrapper { 
    static F* func_; 
    static uint64_t func(void* p) { return (*func_)(p); }  
    friend WeightFunc make_function_pointer<>(F& f);  
    static WeightFunc get_function_pointer(F& f) { 
     if (!func_) func_ = new F(f); 
     return func; 
    } 
}; 

template<class F> F* lambda_wrapper<F>::func_ = 0; 

// ... 
WeightFunc fp = make_function_pointer([](void* param) -> uint64_t { return 0; }); 
+8

值得一提的是,轉換爲函數指針只是無狀態的lambda函數,它們不能捕獲詞法範圍。 – 2010-07-24 10:08:01

+0

轉換爲函數指針似乎不適用於g ++ 4.5模板代碼(http://tinyurl.com/3y6hkyq) – rafak 2010-08-06 00:08:23

+0

請參閱http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45080 。 – 2010-08-07 14:44:40

-1

嘗試(未測試):

#include <function> 

typedef std::function< int64_t (void*) > weight_func; 
typedef std::map<std::string, weight_func > CallbackTable; 

我不認爲有任何其他方式做到這一點,而不是使用std ::函數或同等學歷。

+0

感謝修復sbi – Klaim 2010-07-23 18:56:03

+3

不要使用'std :: function ',使用'std :: function '。 – 2010-07-23 19:01:49

+0

對!修正了,謝謝! – Klaim 2010-07-23 19:28:28

1

如果你真的堅持不使用function<>那麼你很可能decltype:

typedef decltype([](void*)->uint_64{return 0;}) my_lambda_type; 

我真的不推薦,雖然這一點,因爲你大大限制自己,我甚至不知道如果兩個具有相同簽名的lambda保證是相同的類型。

+0

是否保證生成的類型將是相同比如果你寫的確實相同的typedef某處其他?我認爲你不應該認爲這個類型是簽名依賴的......但也許我錯了。 – Klaim 2010-07-23 19:30:07

+0

在GCC中不起作用。 – 2010-08-28 19:53:36

+1

舊的答案,我知道,但lambda表達式不能出現在未評估的上下文中。 (我認爲你提出的理由是:因爲每個lambda表達式都是一個唯一的,未指定的類型,所以你不能保證任何特別有意義的答案和一個未被評估的上下文。) – GManNickG 2011-02-04 06:22:25