I'm trying to map some structs to some other instances, like this:
template <typename T>
class Component {
public:
    typedef std::map<EntityID, T> instances_map;
    instances_map instances;
    Component() {};
    T add(EntityID id) {
        T* t = new T();
        instances[id] = *t;
        return *t;
    };  
};
Then I use it like this:
struct UnitInfos {
    int owner_id;
    int health;
    float x, y;
};
class LogicComponent : public Component<UnitInfos> {};
The problem is that when it later retrieve data later on, like this:
comp.instance[id];
I get a breand new object with properties initialized at default values.
Is there something inherently wrong with this piece of code, or am I leaving out information about the problem?
As per @aaa suggestion, i change the code to
typedef std::map<EntityID, T> instances_map;
instances_map instances;
T& add(EntityID id) {
    instances[id] = T();
    return instances[id];
};
but when I access it
UnitInfos &info = logic_c.instances[id];
the value of info.x is still 0. Any pointers?
The problem was how I stored the reference to LogicComponent in another class. using LogicComponent logic_c; instead of LogicComponent& logic_c;. It now works, but I'm storing pointers in the map (instead of @aaa's suggestion). Is this a bad idea?
Clarify the operations you want to perform on LogicComponent. Assuming you are trying to achieve something like this:
Step 1: Add a new entry to the map:
LogicComponent comp; 
EntityID id = 99;
UnitInfos info = comp.add(id);
Step 2: Initialize the info:
info.x = 10.0;
info.y = 11.0
// etc
Step 3: Get the info object again:
UnitInfos info2 = comp.instances[id]; // this is uninitialized.
Then, a few code comments are in order:
The info object returned by comp.add is a COPY of the object you added to the map. By modifying it, you are not modifying what is in the map.
The simplest fix is to create a map of pointers to the object instead of the object itself.
typedef std::map<EntityID, T*> pinstances_map;
T * add(EntityID id) {
    T* t = new T();
    instances[id] = t;
    return t;
};  
// initialize as 
UnitInfo *info = comp.add(id);
info->x = 10.0;
info->y = 11.0;
// retrieve as 
UnitInfos *info = comp.instances[id];
Also, do use an accessor method to get the mapped value, instead of exposing the map object as public. Make the instances variable protected, and add a public get() method.
Edit: This code works fine for me:
#include <map>
#include <iostream>
using namespace std;
template<typename T>
class Component
{
public:
        typedef map<long, T*> pinstances_map;
        pinstances_map instances;
        T * add(long id)
        {
                T *t = new T();
                instances[id] = t;
                return t;
        }
};
struct UnitInfo 
{
        float x, y;
};
class LogicComponent: public Component<UnitInfo> {};
int main()
{
        LogicComponent comp;
        UnitInfo *info = comp.add(99);
        info->x = 10.0;
        info->y = 11.0;
        UnitInfo *info2 = comp.instances[99];
        cout << info2->x << " " << info2->y;
        return 0;
}
                        might be that
T add(EntityID id) {
    T* t = new T();
    instances[id] = *t;
    return *t;  // return value and map instance are not the same anymore
};  
should be
T& add(EntityID id) {
    instances[id] = T();
    return instances[id];
};  
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With