unordered_map assistance

I am currently trying to use a unordered_map to store a bunch of "monsters". Side note im trying to create a tested based rpg. (using boost map isnt an option)

so far i have
unordered_map<int,Monster> MManifest;// this is in the header
** the above doesnt work because there is no default constructor for it now im curious what to use now**
1
2
3
4
5
6
7
8
9
10
11
12
void Monster::Manifest()
{
	// Make HashTable
	MManifest[1] = Monster("Goblin",1,50,50,10,10,7,3,1,1,2,1);

}
Monster Monster::Summon(int key)
{
	Manifest();
	return MManifest[key];

}


logically it looks like it works, im just curious how to call a monster from a unordered map with a key and return the monster datatype to a variable that is a monster datatype elsewhere.

the value in the () are just name followed by stat values such as lvl, hp, max hp, mp, max mp, etc, etc, etc.

if anyone can suggest another way if any to store for example 100 "monster" data types and call them using a key so i dont have to type this line
Monster("Goblin",1,50,50,10,10,7,3,1,1,2,1)
over and over again when i need it

in addition this may solve my inventory problem too.
inventory would be very similar the only difference it would just be adding stuff to another probably vector or list or table.
closed account (o3hC5Di1)
Hi there,

Could you provide your header file and the compiler error you're getting please?
I would find it odd that the above didn't work for those reasons.

All the best,
NwN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef MONSTER_H
#define MONSTER_H
#include <string>
#include "Being.h"
#include <unordered_map>
using namespace std;
class Monster : public Being
{
public:
	unordered_map<int,Monster> MManifest;

	Monster(string,short,int,int,int,int,short,short,short,short,long,int);
	Monster(const Monster& copy);
	//void Manifest();
	//Monster Summon(int key);
};
#endif




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1
1>  Monster.cpp
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\unordered_map(227): error C2512: 'Monster::Monster' : no appropriate default constructor available
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\unordered_map(221) : while compiling class template member function 'Monster &std::tr1::unordered_map<_Kty,_Ty>::operator [](int &&)'
1>          with
1>          [
1>              _Kty=int,
1>              _Ty=Monster
1>          ]
1>          c:\users\gregory\documents\visual studio 2010\projects\smallfantasy\smallfantasy\monster.h(10) : see reference to class template instantiation 'std::tr1::unordered_map<_Kty,_Ty>' being compiled
1>          with
1>          [
1>              _Kty=int,
1>              _Ty=Monster
1>          ]
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\unordered_map(227): error C2228: left of '.first' must have class/struct/union
1>  Generating Code...
1>  Compiling...
1>  Combat.cpp
1>  Generating Code...
1>  Skipping... (no relevant changes detected)
1>  main.cpp
1>  Story.cpp
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
closed account (o3hC5Di1)
Hi there,

I've looked into it, apparently the map's valuetype does need a default constructor indeed.
Is there any specific reason you don't want to use a default constructor?

You may also like to look into the creational family of design patterns, such as factories, which are actually intended to tackle the thing you're trying to do.

All the best,
NwN
can you provide an example of factory pattern or link to one? i havent been able to find a clean uncomplicated example
Last edited on
It's a good idea to avoid unnecessary default constructors.

This calls the default constructor (see the docs on operator[] to find out why):
MManifest[1] = Monster("Goblin",1,50,50,10,10,7,3,1,1,2,1);

This doesn't:
MManifest.insert(std::make_pair(1, Monster("Goblin",1,50,50,10,10,7,3,1,1,2,1);

This doesn't either, if you're feeling adventurous:
1
2
3
MManifest.emplace(std::piecewise_construct,
                  std::forward_as_tuple(1),
                  std::forward_as_tuple("Goblin",1,50,50,10,10,7,3,1,1,2,1));


Last edited on
If you don't use the methods of unordered_map which require the value_type to have a default constructor, then value_type doesn't need to have a default constructor.

There are a lot of questionable things about your design, not least of which is why every monster object should contain a map of monsters, so the following code differs from your design, but should illustrate how one could use a map without a default constructor. (Note that, the way things are currently implemented, it would make more sense to just construct a monster object and return it than to use a map, however for illustrative purposes:)

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
#include <string>
#include <unordered_map>
using namespace std;

unordered_map<int,Monster> MManifest;

class Monster
{
    enum { Key=1 };

public:

    Monster(string,short,int,int,int,int,short,short,short,short,long,int) {}
    Monster(const Monster& copy) {}
	static Monster Summon();
};

Monster Monster::Summon()
{
    auto it = MManifest.find( Key ) ;

    if ( it == MManifest.end() )
    {
        auto pair = MManifest.emplace(std::make_pair(Key, Monster("Goblin", 1, 50, 50, 10, 10, 7, 3, 1, 1, 2, 1))) ;
        if ( pair.second == true )
            return *pair.first ;
        else
            throw ;      // obviously you'll want to do something more here on a failed insertion.
    }
    else
        return it->second ;
}

int main()
{
    Monster m = Monster::Summon() ; 
}
Last edited on
let me define what i really want to do.

i want to make a monster manifest where i can just return a monster object when i summon it so i dont have to type this line all over the place
Monster("Goblin", 1, 50, 50, 10, 10, 7, 3, 1, 1, 2, 1)

or different forms of this line such as

Monster("Shaman Goblin", 1, 50, 50, 100, 100, 5, 5, 10, 10, 2, 1)


so in the end i have both of this line some where in a data structure ready to be called when i use for example a summon function with a parameter int key.
Also, this way it makes it easier to edit the stats of each monster

Side note, it doesnt need to be in a unordered_map it just seemed logical to.
Open to suggestion like factory pattern but im curious how to use that in this situation.

Topic archived. No new replies allowed.