2014-02-15 39 views
0

我正在研發2D遊戲引擎,並且我不斷遇到模板問題。所以,這一個,我有一個模板函數是這樣的:字符串映射和模板函數指針

template <class T> 
T *S2M_CreateObject(int x, int y) { 
    return new T(x, y); 
} 

現在,我想遊戲從文件加載水平數據,這包括加載和實例對象的派生類,所以我做了一個std ::地圖是這樣的:

map <string, Object *(*)(int x, int y)> o { 
    { "warp", &S2M_CreateObject<Warp> } 
}; 

存儲,我將使用在關卡編輯器來指確定類的字符串,並將其映射到一個函數指針將創造者的一個實例說班。

我希望你明白,這是我最喜歡的方法,但它不起作用。但是,如果我刪除Warp模板說明符(Warp是Object的派生類),它就可以工作,但這不是目標。我知道我可以爲我在遊戲中定義的每種對象類型創建一個函數,但是因爲我正在編寫一個遊戲引擎,所以我無法弄清楚用戶將創建多少個Object-derived類,我不能指望他/她編程每個功能。

任何其他方式我可以做到這一點?

回答

1

鑑於Warp*可以隱式轉換到Object*,指針返回一個函數Warp*不能隱式轉換爲一個指針指向一個函數返回Object*。一般來說,這種轉換也不能安全地執行在所有

現在你的代碼不工作的原因應該清楚。 &S2M_CreateObject<Warp>的類型爲Warp* (*)(int, int),並且不能將其隱式轉換爲Object* (*)(int, int)。相反,你可以使S2M_CreateObject功能總是返回Object*無論哪個類型的實際創建:

#include <map> 
#include <string> 
using namespace std; 

struct Object { 
    Object() {} 
    Object(int x, int y) {} 
}; 
struct Warp : Object { 
    Warp() {} 
    Warp(int x, int y) {} 
}; 

template <class T> 
Object* S2M_CreateObject(int x, int y) { 
    return new T(x, y); 
} 

int main() { 
    map<string, Object *(*)(int x, int y)> o { 
     { "warp", &S2M_CreateObject<Warp> } 
    }; 
} 
+0

謝謝,就是這樣。你讓我今天一整天都感覺很好!我會盡量記住,當處理指向子類的指針時。 – MikiLoz

0

感謝您之前的幫助,我就做這樣的事情:這裏是某種工作結果(簡體) 。我用它具有相當簡單的範圍功能

//Define your template function 
template<typename Type> 
void fnRangeValue(CMyClass * poMyObject, std::string strFormat){ 
    Type tMyField, tMinValue, tMaxValue; 
    /*Do what you have to here!*/ 
} 

//Define a macro for your pointerFunction 
typedef void (*fnPointerFunctionRange)(CMyClass * poMyObject, std::string strFormat); 
// Define your lookup table (map) 
const std::map<std::string, fnPointerFunctionRange> ST_FORMAT_RANGE_POINTER= { 
     {"UINT8",&fnRangeValue<uint8_t>}, 
     {"STR1UINT8",&fnRangeValue<uint8_t>}, 
     {"UINT16",&fnRangeValue<uint16_t>}, 
     {"STR2UINT16",&fnRangeValue<uint16_t>}, 
     {"STR4UINT16",&fnRangeValue<uint16_t>}, 
     {"UINT32",&fnRangeValue<uint32_t>}, 
     {"INT8",&fnRangeValue<int8_t>}, 
     {"INT16",&fnRangeValue<int16_t>}, 
     {"STR3INT16",&fnRangeValue<int16_t>}, 
     {"INT32",&fnRangeValue<int32_t>}, 
     {"FLT32",&fnRangeValue<float>}, 
     {"FLT64",&fnRangeValue<double>}, 
     {"STR7FL64",&fnRangeValue<double>}, 
     {"STR8FL64",&fnRangeValue<double>}, 
}; 

void fnRangeField(CMyClass * poMyObject){ 
    std::string strFormat; 
    fnPointerFunctionRange poFonctionRange; 
    strFormat = "UINT8"; 
    auto itMapRangePointer = ST_EOIIM_FORMAT_RANGE_POINTER.find(strFormat); 
    if(itMapRangePointer != ST_FORMAT_RANGE_POINTER.end()){ 
     poFonctionRange = ST_FORMAT_RANGE_POINTER.at(strFormat); 
     // Call of the right template function thanks to pointers 
     poFonctionRange(poMyObject,strFormat); 
    } 
} 

希望它能幫助你!