Class with static variable, within Template class

I am trying to define a static data member within a class.. Which is within a template class, making each variation of the class have its own value.

Get an error:
undefined reference to `eResource::Obj_Property<eResource::Obj_Tile>::Attribute::labels'

I define it like so:
1
2
3
4
template<>
   map<string, int>
      eResource::Obj_Property<eResource::Obj_Tile>
         ::Attribute::labels;


Which is exactly the same, note I am only using template specializations rather than shorten the code with a given template class, this is because I could not get variations of Obj_Property<> without it saying a data member for a specific specialization was not declared.

Class Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
class eResource
{
public:
   //typedef unsigned char TCOUNT_TYPE;
   enum OBJ_E { OBJ_TILE, OBJ_ITEM, OBJ_NPC, OBJ_MONSTER };
   enum SPR_E { SPR_TILE, SPR_ITEM, SPR_NPC };

   //Property definitions - recursive derivation
   template<class T>
      class Obj_Property
   {
   public:
      //Holds attributes, accessible through index/string
      class Attribute
      {
      public:
         vector<unsigned char>
            values;
         static map<string, int>
            labels;

         unsigned char& operator[] (int index)
         { return values(index); }
         unsigned char& operator[] (string str)
         { return values( labels[str] ); }

         int add(string label, int value)
         {
            int index = values.size();
            values.push_back(value);

            labels["a"] = 1;  //Test, this causes error

            return index;
         }

         bool set(string label, int value)
         {
            //cout << (labels.find(label)->first);
            return false;
         }
      } attribute;

      static OBJ_E Type;
      string name;
      string description;

      Obj_Property(string name = "Unnamed", string description = ""):
         name(name), description(description)
      { }
   };

   class Obj_Tile:
      public Obj_Property<Obj_Tile>
   {
      bool isSolid;
      bool isUseable;
      unsigned char sprite;
   };

   class Obj_Item:
      public Obj_Property<Obj_Item>
   {
      bool isMoveable;
      float value;
      bool isContainer;
      unsigned char sprite;
      Attribute attributes;
   };
   //

   static vector <Obj_Tile>
      Obj_Tiles;
   static vector <Obj_Item>
      Obj_Items;
};


Declaration Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
vector<eResource::Obj_Tile>
   eResource::Obj_Tiles(1);
vector <eResource::Obj_Item>
   eResource::Obj_Items(1);

template<>
   eResource::OBJ_E
      eResource::Obj_Property<eResource::Obj_Tile>
         ::Type = eResource::OBJ_TILE;
template<>
   eResource::OBJ_E
      eResource::Obj_Property<eResource::Obj_Item>
         ::Type = eResource::OBJ_ITEM;

template<>
   map<string, int>
      eResource::Obj_Property<eResource::Obj_Tile>
         ::Attribute::labels;  //Bad definition?
template<>
   map<string, int>
      eResource::Obj_Property<eResource::Obj_Item>
         ::Attribute::labels;  //Bad definition? 


So as you can see, there is a base class template for Obj_Property, within that is a class with a created instance attribute. Attribute has a static data member labels, the data stored in labels must be shared among every instance of Obj_Property<Same Class>, and unique to each type.

I'm in desperate need of help, it would be good if someone could also write in words how C++/Compiler uses templates to achieve my goal.

Thanks to all and everybody who has taken the time to read this, all input is most definitely welcome.

Chris
First attempt at an answer:
Attribute::labels cannot be specialised because it is a normal (non template) class - so no
matter what type the object_property<T>class is instantiated with, it will have no effect on the Attribute class.

You will need to make Attribute a template too??
Oh right, that makes sense. Will try that! :)
Thankyou.
ops
Last edited on
I am defining the map wrong:
template<>
map<string, int>
eResource::Attribute<eResource::Obj_Tile>::labels;

Error:
undefined reference to `eResource::Attribute<eResource::Obj_Tile>::labels'
Last edited on
All that nested classes really make things hard to read though...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
class eResource
{
public:
    //typedef unsigned char TCOUNT_TYPE;
    enum OBJ_E { OBJ_TILE, OBJ_ITEM, OBJ_NPC, OBJ_MONSTER };
    enum SPR_E { SPR_TILE, SPR_ITEM, SPR_NPC };

    //Property definitions - recursive derivation
    template<typename T>
    class Obj_Property
    {
    public:
        //Holds attributes, accessible through index/string
        template<typename U>
        class Attribute
        {
        public:
            vector<unsigned char>
                values;
            static map<string, int>
                labels;


            unsigned char& operator[] (int index)
            { return values(index); }
            unsigned char& operator[] (string str)
            { return values( labels[str] ); }

            int add(string label, int value)
            {
                int index = values.size();
                values.push_back(value);

                labels["a"] = 1;  //Test, this causes error

                return index;
            }

            bool set(string label, int value)
            {
                //cout << (labels.find(label)->first);
                return false;
            }
        } ;
        Attribute<T> attribute;

        static OBJ_E Type;
        string name;
        string description;

        Obj_Property(string name = "Unnamed", string description = ""):
        name(name), description(description)
        { }
    };

    class Obj_Tile:
        public Obj_Property<Obj_Tile>
    {
        bool isSolid;
        bool isUseable;
        unsigned char sprite;
    };

    class Obj_Item:
        public Obj_Property<Obj_Item>
    {
        bool isMoveable;
        float value;
        bool isContainer;
        unsigned char sprite;
    };
    //

    static vector <Obj_Tile>
        Obj_Tiles;
    static vector <Obj_Item>
        Obj_Items;
};



vector<eResource::Obj_Tile> eResource::Obj_Tiles(1);
vector <eResource::Obj_Item> eResource::Obj_Items(1);

template<>
eResource::OBJ_E eResource::Obj_Property<eResource::Obj_Tile>::Type = eResource::OBJ_TILE;

template<>
eResource::OBJ_E eResource::Obj_Property<eResource::Obj_Item>::Type = eResource::OBJ_ITEM;


template<typename T>
template <typename U>
map<string, int> eResource::Obj_Property<T>::Attribute<U>::labels;   



Testing testing...

1
2
3
4
5
6
7
8
9
10
11
12
int main()
{   

    eResource er;


    eResource::Obj_Property<eResource::Obj_Item> aa,bb,cc,dd;
    eResource::Obj_Property<eResource::Obj_Tile> zz,yy,xx,ww,vv;

    aa.attribute.labels.insert(make_pair("Hello",1));
    zz.attribute.labels.insert(make_pair("World",2));
}

Last edited on
Yeah, I've decided to split it up. Thanks for that.

1
2
3
template<>
   map<string, int>
      eResource::Attribute<eResource::Obj_Tile>::labels = map<string, int>();  //Seems to work 
Topic archived. No new replies allowed.