0

I'm working on a 2D game engine and I continuosly run into template problems. So, for this one, I've got a templated function like this:

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

now, I would like the game to load the level data from a file, and that includes loading and instantiating Object-derived classes, so I made an std::map like this:

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

which stores a string that I will be using in the level editor to refer a determined class and maps it to a function pointer that would create an instance of that said class.

I hope you get the idea, this is the approach I like the most but it is not working. However, it works if I delete the Warp template specifier (Warp is a derived class of Object), but that is not the goal. I know I could create a function for every object type I have defined in the game, but since I'm programming a game engine, I can't figure out how many Object-derived classes the user will create and I cannot expect him/her to program each function.

Any other way I can do this?

2 Answers 2

1

Whereas Warp* can be implicitly converted to Object*, a pointer to a function returning Warp* cannot be implicitly converted to a pointer to a function returning Object*. Nor, in general, can such a conversion be performed safely at all.

Now the reason why your code doesn't work should be clear. &S2M_CreateObject<Warp> has type Warp* (*)(int, int), and this can't be implicitly converted to Object* (*)(int, int). Instead, you can make the S2M_CreateObject function always return Object* regardless of which type is actually created:

#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> }
    };
}
Sign up to request clarification or add additional context in comments.

1 Comment

thanks, that was it. you made my day! i'll try to remember that when working with pointers to child classes.
0

Thanks to your previous help, I could do something like this: here is somehow the working result (simplified). I used it with a quite simple range function

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

Hope it will help you!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.