2013-01-07 67 views
2

在使用bind實現調度表的過程中,我試圖用替換具有函數模板的宏。如何將此宏轉換爲函數模板?

一旦我開始添加用於返回std::stringdouble的表格,我將強烈推薦使用模板版本。

宏版本工作正常,但模板版本轉儲核心。

有人可以解釋我做錯了什麼嗎?謝謝。

CODE

#include <functional> 
#include <iostream> 
#include <map> 

struct Integer 
{ 
    virtual int getInt() const = 0; 
}; 

struct IntImpl : public Integer 
{ 
    virtual int getInt() const { return 42; } 
}; 

typedef std::function<int()>        IntFunction; 
typedef std::function<IntFunction(Integer const& inst)> IntLambda; 

#define USE_MACRO 

#ifdef USE_MACRO 
#define MP(A,B) \ 
    std::make_pair(A, [](Integer const& inst) { \ 
       return std::bind(B, std::cref(inst)); \ 
      }) 
#else 
template<typename L,typename T,typename M> 
std::pair<std::string,L> 
MP(std::string const& str, M method) 
{ 
    return std::make_pair(str, [&method](T const& inst) { 
     return std::bind(method, std::cref(inst)); 
     } 
    ); 
} 
#endif 

static std::map<std::string,IntLambda> const g_intTbl = 
{ 
#ifdef USE_MACRO 
    MP("getInt", &Integer::getInt) 
#else 
    MP<IntLambda,Integer>("getInt", &Integer::getInt) 
#endif 
}; 

int 
main(int argv, char* argc[]) 
{ 
    IntImpl x; 
    std::cerr << g_intTbl.find("getInt")->second(x)() << std::endl; 
} 
+4

我可能是錯的,但它可能是你通過引用捕獲'method',一個局部變量。 – chris

+0

不用擔心,因爲現有的一個很好。我昨天剛剛讀到關於如何在循環中通過引用捕獲'i'會導致它們全部具有'i'的最終值(假設'i'被聲明在循環之外,以避免UB),所以纔想到:) – chris

+0

@chris - 好點 - 只是去顯示使用引用可以是不平凡的! – kfmfe04

回答

4

你的問題是你如何捕捉method到您的拉姆達。您通過引用捕獲method,該引用是引用本地方法參數(堆棧中的一個值)。 return std::bind()直到調用該函數纔會執行,此時它將嘗試將引用綁定到顯然不再存在的堆棧變量。

您只需將[&method]更改爲[method]以按值捕獲。

+0

看起來不錯 - ty – kfmfe04