字符串和指向模板化函数的指针的映射

Map of strings and pointers to templated functions

本文关键字:函数 指针 映射 字符串      更新时间:2023-10-16

我正在开发一个2D游戏引擎,经常遇到模板问题。所以,对于这个,我有一个模板化的函数,如下所示:

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

现在,我希望游戏从一个文件中加载级别数据,其中包括加载和实例化Object派生的类,所以我制作了一个std::map,如下所示:

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

它存储一个字符串,我将在级别编辑器中使用该字符串来引用一个确定的类,并将其映射到一个函数指针,该指针将创建该类的实例。

我希望你明白,这是我最喜欢的方法,但它不起作用。但是,如果我删除Warp模板说明符(Warp是Object的派生类),它会起作用,但这不是目标。我知道我可以为我在游戏中定义的每一种对象类型创建一个函数,但由于我正在编写游戏引擎,我无法计算用户将创建多少个对象派生类,我也无法指望他/她对每个函数进行编程。

我还有别的办法吗?

虽然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> }
};
}

感谢您之前的帮助,我可以做这样的事情:这是工作结果(简化)。我用了一个非常简单的测距功能

//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);
}
}

希望它能帮助你!