Data Structure that stores object with names - c++

I want to store object that are given a certain name.
I wanted to use struct and then store them in a vector, but it was suggested to me that I should rather use a different data structure, a little more simple, but I cant seem to find one.
My current ("complex") solution:
//in header file
struct objStorage{
Classname obj;
string name;
};
vector<objStorage> vec;
//in constructor
objStorage firstObj;
firstObj.obj = new Classname();
firstObj.name = "foo";
vec.push_back(firstObj);
Is there a more simple solution (Data structure)?
I should add that I don't need the structure once I stored (copied?) it in the vector, because this is all happening in another class (constructor) so I don't want any problems when calling the constructor multiple times.

If you want to lookup items by some key, for example a string, the classic thing to use is a map:
std::map<std::string, Classname> items;
std::pair<std::map<std::string, Classname>::iterator, bool> inserted =
items.insert(std::make_pair(std::string("foo"), Classname()));
items["bar"] = Classname();
In this set up, if you really think you want to use pointers, you should consider some form of smart pointer.
There are other options, for example, C++11 introduces other lookup structures - e.g. unordered maps.

Related

Adding data into map using type alias, alias template

I am new to C++. I am not able to understand this code snippet's logic. Could some help me understand this and help me with the concept loading data into the map using the function defined. Problem Explanation : Param1 refers to variables A and B and Param2 refers to B and C.
class VariableInformation
{
using ParameterNameSet = std::set<std::string>;
using VariableReferences = std::map<std::string, ParameterNameSet>;
VariableReferences m_referencesToVariables;
public:
void addReferenceToVariable(std::string parameterName, std::string variableName)
{
m_referencesToVariables[variableName].insert(parameterName);
}
};
what you are looking at is the new c++11 way of doing typedef. so, a statement like:
using ParameterNameSet = std::set<std::string>;
is equivalent to this:
typedef std::set<std::string> ParameterNameSet;
i know a lot of engineers prefer the new syntax. personally, i am old school. i like the typedef way. to each, their own.
as for what the code does, it defines a map of sets:
VariableReferences m_referencesToVariables;
it then uses the overloaded std::map::operator [] to either access an existing element, or insert one if not there (together with an empty set). the std::map::operator [] returns a reference to it's value (the set) which is then used to insert into. hope this helps.

object, inheritance, dynamic_cast need advice

I know that has been asked a lot, I googled but couldn't put everything together. Maybe because it is not possible to do, what I want?
I have
struct Universe
{
}
and
struct Atom: Universe
{
}
struct Molecule: Universe
{
}
Universe U;
Atom A;
Molecule M;
_atoms = vector<Universe*>(3);
_atoms.push_back(&U);
_atoms.push_back(dynamic_cast<Universe*>(&A));
_atoms.push_back(dynamic_cast<Universe*>(&M));
auto THIS_IS_ATOM = _atoms[1];
This code is most likely wrong in many ways. But my idea was to store different derived structs like this, and later access them from array or list, without any dataloss or class truncating. I wanted to get some element from array, like _atoms[1], and be able to know what type this struc is (Universe, or Atom) and e.t.c
How should I do it properly in C++?
Your code has several problems.
Universe needs a virtual destructor.
You must create your instances on the heap.
You are using the wrong std::vector constructor.
Here is a solution that should work:
struct Universe {
virtual ~Universe() {} // otherwise Atom and Molecule will not be deleted properly
}
struct Atom : Universe {
}
struct Molecule : Universe {
}
std::vector<Universe*> _atoms; // you don't need to pass anything in the constructor
_atoms.reserve(3); // but if you want to make sure that the vector has exactly a capacity of 3, use this
_atoms.push_back(new Universe());
_atoms.push_back(new Atom());
_atoms.push_back(new Molecule());
auto this_is_atom = _atoms[1]; // will actually be equivalent to
Universe* this_is_atom = _atoms[1];
// finally you must delete all the instances which you created on the heap
while (!_atoms.empty()) delete _atoms.back(), _atoms.pop_back();
Addendum: If you need to treat the objects in the vector non-polymorphically, you can cast them to the appropriate types with a static cast:
Atom* a = static_cast<Atom*>(_atoms[1]);
Edit: Instead of using a vector of raw pointers, it is advisable to use a vector of smart pointers instead, for example std::unique_ptr or std::shared_ptr, depending on the ownership semantics you are trying to model.

In a hashmap/unordered_map, is it possible to avoid data duplication when the value already contains the key

Given the following code:
struct Item
{
std::string name;
int someInt;
string someString;
Item(const std::string& aName):name(aName){}
};
std::unordered_map<std::string, Item*> items;
Item* item = new Item("testitem");
items.insert(make_pair(item.name, item);
The item name will be stored in memory two times - once as part of the Item struct and once as the key of the map entry. Is it possible to avoid the duplication? With some 100M records this overhead becomes huge.
Note:
I need to have the name inside the Item structure because I use the hashmap as index to another container of Item-s, and there I don't have access to the map's key values.
OK, since you say you are using pointers as values, I hereby bring my answer back to life.
A bit hacky, but should work. Basicly you use pointer and a custom hash function
struct Item
{
std::string name;
int someInt;
string someString;
Item(const std::string& aName):name(aName){}
struct name_hash
{
size_t operator() (std::string* name)
{
std::hash<std::string> h;
return h(*name);
}
};
};
std::unordered_map<std::string*, Item*, Item::name_hash> items;
Item* item = new Item ("testitem");
items.insert(make_pair(&(item->name), item);
Assuming the structure you use to store your items in the first place is a simple list, you could replace it with a multi-indexed container.
Something along thoses lines (untested) should fulfill your requirements:
typedef multi_index_container<
Item,
indexed_by<
sequenced<>,
hashed_unique<member<Item, std::string, &Item::name
>
> itemContainer;
itemContainer items;
Now you can access items either in their order of insertion, or look them up by name:
itemContainer::nth_index<0>::type & sequentialItems = items.get<O>();
// use sequentialItems as a regular std::list
itemContainer::nth_index<1>::type & associativeItems = items.get<1>();
// uses associativeItems as a regular std::unordered_set
Depending on your needs, you can use other indexings as well.
Don't store std::string name field in your struct. Anyway when you perform lookup you already know name field.
TL;DR If you are using libstdc++ (coming with gcc) you are already fine.
There are 3 ways, 2 are "simple":
split your object in two Key/Value, and stop duplicated the Key in the Value
store your object in a unordered_set instead
The 3rd one is more complicated, unless provided by your compiler:
use an implementation of std::string that is reference counted (such as libstdc++'s)
In this case, when you copy a std::string into another, the reference counter of the internal buffer is incremented... and that's all. Copy is deferred to a time where a modification is requested by one of the owners: Copy On Write.
No, there isn't. You can:
Not store name in Item and pass it around separately.
Create Item, ItemData that has the same fields as Item except the name and either
derive Item from std::pair<std::string, ItemData> (= value_type of the type) or
make it convertible to and from that type.
Use a reference to string for the key. You should be able to use std::reference_wrapper<const std::string> as key and pass key in std::cref(value.name) for key and std::cref(std::string(whatever)) for searching. You may have to specialize std::hash<std::reference_wrapper<const std::string>>, but it should be easy.
Use std::unordered_set, but it has the disadvantage that lookup creates dummy Item for lookup.
When you actually have Item * as value type, you can move the name to a base class and use polymorphism to avoid that disadvantage.
Create custom hash map, e.g. with Boost.Intrusive.

Handling 'units' in an RTS game - c++

I'm currently in the process of making a simple RTS style game in c++.
What i'm wondering is how to handle the creation of new units in the game (ie. making marines from the barrack). How would i store these units?
I was thinking of having a class 'unit' which would then be inherited by specific unit types (ie. marines, firebats, etc) but if i create an array for these (ie. Marines myMarines[20]) that will create a hard cap on these units.
How do i create such an array that can be expanded at will?
Thank you!
The standard library provides them std::vector template for dynamically resizable arrays. A std::vector<Marine> would be the most straightforward alternative to Marines myMarines[20].
However, you probably don't want a separate list for each unit type. It is highly likely that you will want to store all units in the same list, regardless of their type. std::vector<Unit> would sound like the obvious solution but it is not. The problem is that std::vector stores the objects by value. The following would not work right:
std::vector<Unit> v;
v.push_back(Marine("John Doe"));
The problem is that the Marine object will be copied into a Unit object, which is what the vector stores. This kind of copy results in a what is known as slicing: all the Marine specific members will be lost, and only those that exist in Unit will be stored.
One solution to this problem is to store pointers in the vector because copying pointers does not change the objects they point to. But that brings other problems. To store pointers, this means you'll need to allocate the objects dynamically. And that means that now you are responsible for destroying those objects manually. That's a tiresome and error-prone task.
The solution is to store in the vector objects that destroy the dynamically allocated objects automatically, instead of pointers. These objects are known as smart pointers. The simplest one that exists in the standard library is std::unique_ptr.
std::vector<std::unique_ptr<Unit>> v;
v.emplace_back(new Marine("John Doe"));
This is a C++11 feature. If your compiler doesn't support it you can find alternatives in the Boost libraries. Boost even includes a container that acts pretty much like a std::vector of std::unique_ptrs: boost::ptr_vector. That would be another alternative.
You will probably benefit from using an std::vector here. This will allow you to add and remove items at will, and handles dynamic memory allocation internally (without concerning you over the nitty-gritty details!).
Say you want to store a list of marines (denoted by an imaginary class CMarine in the following example):
std::vector<CMarine> marinesList;
Now to add a marine simply do this:
marinesList.push_back( CMarine( <whatever-its-constructor-takes> ) );
To access this marine you can do something like this:
CMarine& marine = marinesList.at( 0 );
marine.someVar = 33;
marine.doMethod();
(I use a reference since CMarine could very well be too bulky to pass around by value efficiently)
You can also loop through all the marines with an iterator like so:
for ( std::vector<CMarine>::iterator _it = marinesList.begin();
_it != marinesList.end(); ++_it );
{
CMarine& marine = *_it;
// Now you can do something with this marine reference
}
UPDATE:
If CMarine is polymorphic, that is, it inherits from a superclass (maybe something like CUnit in your case), and you have a 'global' vector of all units - Georg Fritzsche rightly noted that object slicing could occur (if we are storing by value). Instead you might be better off with a vector of CUnit (smart) pointers like this:
std::vector<std::unique_ptr<CUnit>> unitsList;
// To add a marine:
unitsList.push_back( new CMarine( <whatever-its-constructor-takes> ) );
Read more about vectors here.
Chances are that you don't want a separate container for each of your unit types. Therefore, you'll have to generalise a little and either use something like component based design. Once you have that in place, you'll want an std::vector<GameUnit*> or std::list<GameUnit*> in the first case, and an std::vector<GameUnit> or std::list<GameUnit> in the second case. Either way, you should be using a standard library container to store things.
You can find more information on std::vector and std::list on http://cppreference.com, although your book should already cover them. Also, see
First off, I'd create a Unit class and then subclass your units from it, so you don't have to process a bunch of separate lists. Then, I'd store pointers to the units in:
std::list< Unit * > unitList
A list lets you append however many objects you like, and, while it doesn't allow for rapid access to random members of the list, you can iterate through it easily and not have to worry about it trying to move large amounts of memory around when you delete something out of the middle of it.
One thing I like to do is have a unit register itself with the units list automatically from inside the unit's constructor. So assuming Marine is a subclass of Unit, all I would need to do would be to say:
new Marine(x_pos, y_pos);
...and a new Marine would be created and appended to the list automatically.
At this point, each frame, you can iterate through every Unit in unitList and run the unit's update function (which is a virtual function that is different for each subclass).
After the update loop, run a cleanup loop that iterates through unitsList again, finds all destroyed units, and removes them from the list and deletes them.
I say std::vector ! I usually create a base class of unit (or GameObject as I like to call them) Here's what I would have done:
class GameObject {} // Maybe has virtual methods for the Size, Location and Image?
class Barrack
{
std::vector< GameObject > gameUnits;
public:
// code
void AddUnit() { gameUnits.push_back( GameObject() ); }
void DestroyUnit(int index);
// etc. etc.
}
However, if you don't want to rely too much on inheritance, i.e you have different kinds of units and all of them don't inherit from one base class, you may try this vector_any class I implemented some days ago to hold the sprites of my RPG game:
struct element
{
element( void* data, const std::type_info& info ) : value(data), type( &info ) {}
void* value;
const std::type_info* type;
};
class type_conversion_exception : exception {};
class linked_vector
{
vector< element > stack;
public:
linked_vector() {}
template< typename T > void add_item( T& item )
{
stack.push_back( element( static_cast< void* >( &item ), typeid(item) ) );
}
template< typename T > T& get_item( int index )
{
if ( *( stack[index].type ) == typeid( T ) )
{
return *( static_cast< T* >( stack[index].value ) );
}
else throw type_conversion_exception();
}
};
You can use it for your game units like this.
linked_vector gameUnits;
MilitaryUnit mUnit;
AirUnit aUnit;
gameUnits.add_item( mUnit );
gameUnits.add_item( aUnit );
try{ draw( gameUnits.get_item< MilitaryUnit >(0) ); }
catch( type_conversion_exception e ) { /* error handling */ }
// etc. etc.
The choice between vector and list is a tricky one. Every time you push_back() on the vector, the whole vector is reallocated and copied. A list doesn't have this issue. Neverthless, you could preallocated the vector and have a unit cap - this is fine unless you want effectively 'unlimited' units on a map, but you probably don't.
As for lookup, the vector has constant time lookup for any index, but how often would you want to jump to a particular index? When it comes to iterating over a whole list or vector I don't think there's any performance difference.
Also, when you want to remove a Unit (when it's killed) from a vector you would have some more reallocate and shuffle issues, a list can remove any item much more efficiently.
I'm personally leaning towards a list.
And as already stated the container you choose should hold pointers to the unit base class.

Extending a thrift generated object in C++

Using the following .thrift file
struct myElement {
1: required i32 num,
}
struct stuff {
1: optional map<i32,myElement> mymap,
}
I get thrift-generated class with an STL map. The instance of this class is long-lived
(I append and remove from it as well as write it to disk using TSimpleFileTransport).
I would like to extend myElement in C++, the extenstions should not affect
the serialized version of this object (and this object is not used in any
other language). Whats a clean way to acomplish that?
I contemplated the following, but they didn't seem clean:
Make a second, non thrift map that is indexed with the same key
keeping both in sync could prove to be a pain
Modify the generated code either by post-processing of the generated
header (incl. proprocessor hackery).
Similar to #2, but modify the generation side to include the following in the generated struct and then define NAME_CXX_EXT in a forced-included header
#ifdef NAME_CXX_EXT
NAME_CXX_EXT ...
#endif
All of the above seem rather nasty
The solution I am going to go with for now:
[This is all pseudo code, didn't check this copy for compilation]
The following generated code, which I cannot modify
(though I can change the map to a set)
class GeneratedElement {
public:
// ...
int32_t num;
// ...
};
class GeneratedMap {
public:
// ...
std::map<int32_t, GeneratedElement> myGeneratedMap;
// ...
};
// End of generated code
Elsewhere in the app:
class Element {
public:
GeneratedElement* pGenerated; // <<== ptr into element of another std::map!
time_t lastAccessTime;
};
class MapWrapper {
private:
GeneratedMap theGenerated;
public:
// ...
std::map<int32_t, Element> myMap;
// ...
void doStuffWIthBoth(int32_t key)
{
// instead of
// theGenerated.myGeneratedMap[key].num++; [lookup in map #1]
// time(&myMap[key].lastAccessTime); [lookup in map #2]
Element& el=myMap[key];
el.pGenerated->num++;
time(&el.lastAccessTime);
}
};
I wanted to avoid the double map lookup for every access
(though I know that the complexity remains the same, it is still two lookups ).
I figured I can guarantee that all insertions and removals to/from the theGenerated)
are done in a single spot, and in that same spot is where I populate/remove
the corresponding entry in myMap, I would then be able to initialize
Element::pGenerated to its corresponding element in theGenerated.myGeneratedMap
Not only will this let me save half of the lookup time, I may even change
myMap to a better container type for my keytype (say a hash_map or even a boost
multi index map)
At first this sounded to me like a bad idea. With std::vector and std::dqueue I can
see how this can be a problem as the values will be moved around,
invalidating the pointers. Given that std::map is implemented with a tree
structure, is there really a time where a map element will be relocated?
(my above assumptions were confirmed by the discussion in enter link description here)
While I probably won't provide an access method to each member of myElement or any syntactic sugar (like overloading [] () etc), this lets me treat these elements almost a consistent manner. The only key is that (aside for insertion) I never look for members of mymap directly.
Have you considered just using simple containership?
You're using C++, so you can just wrap the struct(s) in some class or other struct, and provide wrapper methods to do whatever you want.