My problem is quite peculiar in that I have a solution, but it is in my opinion extremely poor and I am looking for a better one. Here's the problem:
There's a file that needs to be loaded and have characteristics to create a bunch of objects. The object will have 10-12 properties and there will be a few types of objects each one with different characteristics. To make it even more fun, there's one type of object that is actually made up of two separate other objects, but that can be ignored for the purpose of this question. The file will store the characteristics for a few objects as well as the base class. For example the base class will contain the "car" manufacturer, factory made and maybe the engine used, but each of the objects will contain other data unique to each model; model name, tires, or whatever you can think of.
At the moment I have the cars loaded into a map, from the file:
std::map<std::string,std::string> loadCars(std::string filePath);
This way I can just pass this map to each of the objects constructors and it'll look for the key it needs (For example one model might need to check for the types of sunroof used whilst another doesn't have a sunroof, so can ignore it) and initialize the data. It'll load the car model name into the object name etc, like this:
Car ford = new Car(std::map loadCars(cars.txt);
Now here's the problems, from minor to major:
1) If three car models are loaded in and none of them have sunroofs, the sunroof field in the map will be unitiliazed when its passed to the constructors, I dont know if this will cause errors, so I will require a function that pre-initializes the map with empty values, which I don't think is too bad.
2) And here's the major problem and why this solution does not work:
Some of the values in the car file are arrays. Meaning that an std::string in the map will not store them. Now the solution I have at the moment to me appears very ugly:
std::map<std::string, std::vector<std::string>> loadCars(std::string);
So I pass this map to the constructor and for each of the vectors it has to check if it has more than one value. For example model name would not, so it would be hardcoded to put that one value in a string. Or if this particular car only has one type of tire but normally they have multiple types, it'll just put in the vector with one element.
The problem is that when doing the actual file loading absolutely everything will have to be converted from simple strings like the string for the model name into a vector. This seems like a waste and very shoddy code.
Are there any better ways of doing this? Ideally you'd have a map-like container where the second value can either be a vector or a string but I dont think those exist.
Related
My goal here is to create a unique ID (starting a 0) for each child of a specific class. I'm not sure if it is possible in the way i want, but i figured i'd ask here as a last resort.
Some context:
I'm creating my own 2D game engine and i want it to have an ECS as it's back bone (Before anyone says anything, i'm doing this as a learning experience, i know i could just use an already existing game engine). My idea is that each class that implements the 'EntityComponent' class should have a unique ID applied to it. This needs to be per child, not per object. I want to use this ID as the index for an array to find the component of an entity. The actual ID that each Component gets is unimportant and each component does not need to be assigned the ID every run time.
My hope is there is some way to create something similar to a static variable per class (That implements the Entity Component class). It needs to be quick to get this value so doing an unordered_map lookup is slower than i would like. One thing i do not want to do is setting the ID for every component myself. This could cause problems once many components are made and could cause problems if i forget to set it or set two components to the same ID.
One idea i had was to make a variable in EntityComponent called ID (And a getter to get it). When the entity is constructed it looks up an unordered map (which was made at run time, assigning an ID to each class) for what ID it should have. The price of looking up once at construction is fine. The only problem i see with this is there is a lot of redundant data (Though overall it seems it would account to a pretty small amount). With this, every single transform component would have to store that it its ID is x. This means potentially thousands upon thousands of transform components are storing this ID value, when only 1 really needs to.
Basically i am after an extremely quick way to find an ID for a class TYPE. This can be through a lookup, but it needs to be a quick lookup. I would like something faster than unordered_map if possible. If this can be done through compile time tricks (Maybe enums?) or maybe even templates i would love to hear your ideas. I know premature optimisation is the bad, but being able to get a component fast is a pretty big thing.
What i'm asking might very well be impossible. Just thought i'd ask here to make sure first. I should also note i'm trying to avoid implementation of this in the children classes. I'd like to not have to set up the same code for each child class to create an id.
Thank you.
In order to get something corresponding to the actual type of an object, it either needs to be in the object itself or accessed via a virtual function. Otherwise the type will be determined by the type of the variable it is associated with.
A common option when speed and size are both important is to have an integer identifier associated with each type (when the full type list is known at compile time) and use that integer value in a specific way when you want to do something based on the type.
The integer mechanism usually uses an enum for generating the corresponding value for each type and has that field in every object.
The virtual method variety, I've used boost::uuid and a static data member in each class and a virtual method get'er for it.
Declare a virtual function newId() in EntityComponent.
Implement this function to get and increment a static variable in each class, which children you want to have a unique Id.
Assign Id in the constructor:
mId = newId();
don't know this if this is what you meant and i know this is an old post however this is how im currently dealing with a similar issue, maybe it will help someone else.
(Im also doing this as a learning experience for uni :) )
in the controlling class or its own utility class:
enum class EntityType{ TYPE_ONE = 0, TYPE_TWO =1};
in class header:
#include "EntityType.h"
class Whatever{
public:
inline void getType(){return _type;}
OR
inline void getType(){return EntityType::TYPE_ONE;}
private:
EntityType _type = EntityType::TYPE_ONE;
};
Hope this is helpful to anyone :)
Basically, Im writing a small database/inventory system for a game. The item class and its sub-classes (weapon, armor, consumable, etc) are all finally up and working. My vector for inventory is written within a separate inventory class (allows more than one inventory - i.e. enemies can have them too!) and at this point, the inventory is FAR from written - there is still no drop function, etc.
but im taking this one step at a time because its a learning experience.
basically I believe in this case, pointers are the answer. this code seems to work (have not tried it yet)
Weapon DebugDagger{ 1, "Debug Dagger", "Debug Dagger given to you by Help", 25 };
Armor DataCloak{ 2, "Data Cloak", "Data Cloak given to you by Help", 10 };
Item *pItem = &DebugDagger;
Weapon *pWeapon = &DebugDagger;
InventoryManager PlayerInv;
PlayerInv.pickupItem(pWeapon);`
in this case, pickupItem(Item*) is taking a static Item type - which is the base class for my function, where the weapon being added to the inventory is a sub-class (class Weapon : public Item{})
the way this is written seems to hack together a solution, but it would be MUCH easier if I could just write the pointer into the class functions themselves so that EACH item created in a sub-class automatically will create a pointer of itself to the base class so I can add it into the inventory subsystem. Is there a way to do this from Within the class? so that EACH member gets a pointer created automatically upon class creation? When I try to use the name variable in the constructor to do this, it does not work, as it seems I have to create the member BEFORE making a pointer, so I dont see how to do it at the same time anticipating a new member being created.
I mean, I'm all for other more effective ideas than a std::vector inventory; for an inventory - I think some function that actually can simply accept the members of any class and record them would be FAR more effective in the long run, but I do not believe this is possible - I think that creating pointers to Item from the sub-classes would still be necessary - seeing as, really, its all items, with each sub function having a single extra specifier ONLY being used for its own function, weapon has attack, consumable has restoration, etc -and its ALL integers, so really those are the same as each other almost, but for function reasons, like equipping, using, classifying, they each get a separate type I suppose I couldve made a SpecialItem subclass to cover it all, but that would be very ambiguous, and leave little room for innovation should a specific type need modification later.
I just dont see it if there is an alternative. if there is direct me and I will read voraciously until I find understanding of it.
Not sure if i got the point, but a pointer to the subclass (Weapon) is already a pointer to the base class (Item).
So you can store all your items (Weapon : Item, Arnmor : Item, ...) in your
std::vector<Item*> Inventory
It does not seem to work this way, because by default NO pointer is being created, in this instance I Had to write one on the fly after creating the Item in order for it to push_back.
otherwise it tells me class Weapon cannot be converted to Item * and wont compile.
so it seems to me that I CAN"T store them into the vector -- for that to work it would have to be
std::vector<Weapon*> Inventory
basically I need the functionality of
std::vector<Weapon*> Inventory
std::vector<Armor*> Inventory2
std::vector<Consumable*> Inventory3
std::vector<Item*> Inventory4
except I need it in ONE single inventory class...
my problem is right now I ONLY have
std::vector,
and NO other class type is ALLOWED to be inserted into this slot, because I have to either convert the type manually (since memory can't do it on its own, the special characteristics have to be dropped), or create a pointer to Item* so that when I insert the POINTER like this:
Inventory.push_back(POINTER);
it will BELIEVE the weapon is an Item, and go ahead with the operation.
otherwise
Inventory.push_back(WEAPON), etc do not work... only Inventory.push_back(Item*)
I dont know if this has been any more clear, but it should make it understandable why I need the pointer. Since I cannot cast a Weapon or even a Weapon * as an Item, I have to create a pointer to Item somewhere in the class function, so that way I have some variable I could automatically pop into the push_back function INSTEAD of the member of the class itself - I sort of have to cloak a weapon or potion as a basic item in order to get it to fit into the vector, because it only accepts basic items as is.
Well, either way - the code ended up being NONFUNCTIONAL IN ENTIRETY.
regardless of this, I need a way to create a database of all members of each type of class.
I need the functionality of a vector, that will work with any type -- or a method to get a vector to accept any type.
I gave up on this method, because it just will not work to have one vector alone.
now Im working on a 3 vector class of obtained item names, quantities, and IDs.
it seems a bit** to figure out how to associate the 3 and also scan through them in unison to make data make sense (I.e. see if item name x, id 32 is in inventory, if it is, allow user to examine such item for details).
this is my first big project really. its a doozy for me.
Assume I want to implement class A which must load its "configuration" from a file. And let's assume the "configuration" is a simple map<string, string>.
I can implement the A::LoadConfiguration in two different ways:
void A::LoadConfiguration(string filename)
map<string, string> A::LoadConfiguration(string filename) const
Should I prefer either of the two implementations, and why?
If you prefer the second version when the user wants to get info on a file they will base all their algorithms on the map. If you do the second version, meaning the implementation may be a map, but doesn't have to be, they can base their code around an API which does not have to change even if the internal implementation does.
Consider the situation where later you realize it is far more efficient to use an std array, for whatever reason, now every program using this code has to change many of it's algorithms. Using the first version the change to array can be handled internally and reflect no changes on the outside.
Now if you are planning to make multiple instances of the class you will definitely want to make it a static method because you don't want the file to load every time you call the constructor (especially if the file will not change).
Completely ignoring your suggestions, but this is probably how I would do it (not knowing all your constraints, so ignore me if it does not fit):
class A
{
public:
static A fromConfiguration( string fileName );
/* ... */
}
In most cases, the "configuration" of a class should be set at object creation, so forcing the user to provide it on construction is a good thing (instead of having to remember to do do the loading later).
namespace NeatStuff
{
map<string,string> loadSimpleConfiguration( string fileName );
}
If the configuration file format is really simple (and not specific to your class) you can move the actual loading out of the class.
Assuming other classes use the configuration later, I prefer option 1, and an additional GetConfigurationParameter public const method that gets the config value for a particular key. That lets me make other classes which can just ask for some parameter by name without ever caring that it's implemented as a map.
Another reason why I prefer option 1 is that loading a configuration should be distinct from returning it. If I see a name like LoadConfiguration, I assume that it loads the config from somewhere and sets the parameters in the class. I do not assume it returns some description of the configuration, which I'd instead expect from a method like GetConfiguration - but opinions on this will vary for different people of course.
I have a class, let's say Person, which is managed by another class/module, let's say PersonPool.
I have another module in my application, let's say module M, that wants to associate information with a person, in the most efficient way. I considered the following alternatives:
Add a data member to Person, which is accessed by the other part of the application. Advantage is that it is probably the fastest way. Disadvantage is that this is quite invasive. Person doesn't need to know anything about this extra data, and if I want to shield this data member from other modules, I need to make it private and make module M a friend, which I don't like.
Add a 'generic' property bag to Person, in which other modules can add additional properties. Advantage is that it's not invasive (besides having the property bag), and it's easy to add 'properties' by other modules as well. Disadvantage is that it is much slower than simply getting the value directly from Person.
Use a map/hashmap in module M, which maps the Person (pointer, id) to the value we want to store. This looks like the best solution in terms of separation of data, but again is much slower.
Give each person a unique number and make sure that no two persons ever get the same number during history (I don't even want to have these persons reuse a number, because then data of an old person may be mixed up with the data of a new person). Then the external module can simply use a vector to map the person's unique number to the specific data. Advantage is that we don't invade the Person class with data it doesn't need to know of (except his unique nubmer), and that we have a quick way of getting the data specifically for module M from the vector. Disadvantage is that the vector may become really big if lots of persons are deleted and created (because we don't want to reuse the unique number).
In the last alternative, the problem could be solved by using a sparse vector, but I don't know if there are very efficient implementations of a sparse vector (faster than a map/hashmap).
Are there other ways of getting this done?
Or is there an efficient sparse vector that might solve the memory problem of the last alternative?
I would time the solution with map/hashmap and go with it if it performs good enough. Otherwise you have no choice but add those properties to the class as this is the most efficient way.
Alternatively, you can create a subclass of Person, basically forward all the interface methods to the original class but add all the properties you want and just change original Person to your own modified one during some of the calls to M.
This way module M will see the subclass and all the properties it needs but all other modules would think of it as just an instance of Person class and will not be able to see your custom properties.
The first and third are reasonably common techniques. The second is how dynamic programming languages such as Python and Javascript implement member data for objects, so do not dismiss it out of hand as impossibly slow. The fourth is in the same ballpark as how relational databases work. It is possible, but difficult, to make relational databases run the like the clappers.
In short, you've described 4 widely used techniques. The only way to rule any of them out is with details specific to your problem (required performance, number of Persons, number of properties, number of modules in your code that will want to do this, etc), and corresponding measurements.
Another possibility is for module M to define a class which inherits from Person, and adds extra data members. The principle here is that M's idea of a person differs from Person's idea of a person, so describe M's idea as a class. Of course this only works if all other modules operating on the same Person objects are doing so via polymorphism, and furthermore if M can be made responsible for creating the objects (perhaps via dependency injection of a factory). That's quite a big "if". An even bigger one, if nothing other than M needs to do anything life-cycle-ish with the objects, then you may be able to use composition or private inheritance in preference to public inheritance. But none of it is any use if module N is going to create a collection of Persons, and then module M wants to attach extra data to them.
I wrote a file parser for a game I'm writing to make it easy for myself to change various aspects of the game (things like the character/stage/collision data). For example, I might have a character class like this:
class Character
{
public:
int x, y; // Character's location
Character* teammate;
}
I set up my parser to read in from a file the data structure with syntax similar to C++
Character Sidekick
{
X = 12
Y = 0
}
Character AwesomeDude
{
X = 10
Y = 50
Teammate = Sidekick
}
This will create two data structures and put them in a map<std::string, Character*>, where the key string is whatever name I gave it (in this case Sidekick and AwesomeDude). When my parser sees a pointer to a class, like the teammate pointer, it's smart enough to look up in the map to fetch the pointer to that data structure. The problem is that I can't declare Sidekick's teammate to be AwesomeDude because it hasn't been placed into the Character map yet.
I'm trying to find the best way to solve this so that I can have my data structures reference objects that haven't yet been added to the map. The two easiest solutions that I can think of are (a) add the ability to forward declare data structures or (b) have the parser read through the file twice, once to populate the map with pointers to empty data structures and a second time to go through and fill them in.
The problem with (a) is that I also can decide which constructor to call on a class, and if I forward declare something I'd have to have the constructor be apart from the rest of the data, which could be confusing. The problem with (b) is that I might want to declare Sidekick and AwesomeDude in their own files. I'd have to make my parser be able to take a list of files to read rather than just one at a time (this isn't so bad I guess, although sometimes I might want to get a list of files to read from a file). (b) also has the drawback of not being able to use data structures declared later in the constructor itself, but I don't think that's a huge deal.
Which way sounds like a better approach? Is there a third option I haven't thought of? It seems like there ought to be some clever solution to this with pointer references or binding or something... :-/ I suppose this is somewhat subjective based on what features I want to give myself, but any input is welcome.
When you encounter the reference the first time, simply store it as a reference. Then, you can put the character, or the reference, or whatever on a list of "references that need to be resolved later".
When the file is done, run through those that have references and resolve them.
Well, you asked for a third option. You don't have to use XML, but if you follow the following structure, it would be very simple to use a SAX parser to build your data structure.
At any rate, instead of referencing a teammate, each character references a team (Blue team in this case). This will decouple the circular reference issue. Just make sure you list the teams before the characters.
<team>Blue</team>
<character>
<name>Sidekick</name>
<X>12</X>
<Y>0</Y>
<teamref>Blue</teamref>
</character>
<character>
<name>Sidekick</name>
<X>10</X>
<Y>50</Y>
<teamref>Blue</teamref>
</character>
Personally, I'd go with b). Splitting your code into Parser and Validator classes, both operating on the same data structure. The Parser will read and parse a file, filling the data structure and storing any object references as their textual names, leaving the real pointer null in your structure for now.
When you are finished loading the files, use the Validator class to validate and resolve any references, filling in the "real" pointers. You will want to consider how to structure your data to make these lookups nice and fast.
Will said exactly what I was about to write. Just keep a list or something with the unsolved references.
And don't forget to throw an error if there are unsolved references once you finish reading the file =P
Instead of storing Character object in your map, store a proxy for Character. The proxy will than contain a pointer to the actual Character object when the object is loaded. The type of Character::teammate will be changed to this proxy type. When you read in a reference that is not already in your map, you create a proxy and use the proxy. When you load an character which you already have an empty proxy in the map, populate it with your newly loaded character. You may also want to add a counter to keep track of how many empty proxy you have in the map so you know when all referenced characters have been loaded.
Another layer of indirection....it always make programming easier and slower.
One option would be to reverse the obligation. The Map is responsible for filling in the reference
template<T> class SymbolMap // I never could rememeber C++ template syntax
{
...
/// fill in target with thing name
/// if no name yet, add it to the list of thing that will be name
void Set(T& target, std::string name);
/// define name as target
/// go back and fill in anything that needs to be name
void Define(T target, std::string name);
/// make sure everything is resolved
~SymbolMap()
}
that won't interact well with value/moving semantics but I suspect that not much will.