1

Issue about Storeing unknown Data in a Class

How can I provide a class in C++ which is able to store any number of variables each of any type? From inside and outside of the class I would like to read, add, modify and delete these data.

So what I am looking for is maybe a list where the datatypes can vary.

Example how the Usage could look like

Class Object();
Object->Storage->Create("position", "float");    // create
Object->Storage->Write("position", 42.0f);       // write
int Result = Object->Storage->Read("position");  // read
Object->Storage->Delete("position");             // delete

How to do that or why to do it in another Way

My question is if there is a common approach for this problem and what a good solution is. If my thoughts were not correct and there is another technique or place to store data for my aim (next paragraph) please tell me.

Optional Background Information and Context

The reason behind this need is that I am writing a kind of component based game engine. There are Components and Systems. A System could be the title menu or a world level and I can add as many Components to it as I wish. Every game tick, the System calls a specified method over all of its Components. Components are e.g. Physics, Terrain, Draw, Characters, Sound, ... The mentioned unknown data structure is what a Component should be able to store in its System. The Component is nearly static and its state depends on the storage it uses. This Storage system is (together with the event manager) used to communicate between Components.

Edit:

By researches I figured out that what I want is called Data Centered or Data Oriented in software design. Now I have a starting point to do more research on this topic. Thank you Michael Anderson for your answer, probably I will use that.

Community
  • 1
  • 1
danijar
  • 32,406
  • 45
  • 166
  • 297
  • Hash Map is the one you want. – SwiftMango Oct 17 '12 at 05:08
  • the problem might be different data types have different length. You'll have to use pointers. Does `void*` do the trick for you? – John Dvorak Oct 17 '12 at 05:10
  • I am not aware of the `void*` practice but I will google that later this day. But do you think of my idea as a good approach? – danijar Oct 17 '12 at 05:14
  • 2
    Why not have a parent class of all your components that has an OnTick() method, and then have all of your components inherit from it? Why do you need classes that can hold a bunch of types defined like that when you can just have real child classes with "float position;" and whatnot in them? – PherricOxide Oct 17 '12 at 05:16
  • There is an abstract parent class Component with a specific method called by the System every game tick. The reason to store data in the System was to provide Components an communication interface. Because a Component can't expect another Component to be added to the System, all it can do is store data in the System and hope the other Component will use it. The Components should not depend on each other. But I would like to hear your approach more detailed. – danijar Oct 17 '12 at 05:20
  • 1
    There **must** be some code that understands the data that you stored, knowing it's type, meaning and usage. So there must be some meaning of the property, why don't you can just add a member in some derived class to store them? Why use dynamic. Just because in the end of the day you have to do something on that data, which implies that they have the same interface for you to operate on. This is what you need to think before implement the classes, and just abstract the interface, then derive it for the component specific state. – admiring_shannon Oct 17 '12 at 05:27
  • This approach has some real drawbacks - you're giving up all type safety and even intellisense, and have to remember that "this object has a stored property `Position` of type `float`.. or was it `position` of type `int`?". Please don't go down that road. – DCoder Oct 17 '12 at 05:33
  • @DCoder. I can understand your notion. What would you prefer? – danijar Oct 17 '12 at 14:28
  • I'm a believer in strong typing as much as possible - I would go with FamZheng's or PherricOxide's solutions, using proper classes with known data types, instead of this. – DCoder Oct 17 '12 at 16:16
  • Nice, I would like that, too. But **how could the components then be independent from each other but use the save data together?** For example the terrain component and the character component both add meshes to a shared list and the draw component will draw all meshes in this list. – danijar Oct 17 '12 at 17:54

2 Answers2

3

You probably want to use boost::any for this kind of thing.

Your code will look like this:

std::map<std::string,boost::any> object;
object["position"] = 42.0f;

//This will throw if the type is wrong
int Result = boost::any_cast<float>(object["position"]);
object.erase("position");
Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
1

Does the Standard Template Library (STL) - more specifically, the use of a map - not work for your needs?

http://en.cppreference.com/w/cpp/container/map

You can use the map to hold values which are either:

1) a "CustomObject", which is a union of all possible variable / object types.

2) a pointer to the actual objects / variables.

sampson-chen
  • 45,805
  • 12
  • 84
  • 81
  • I really like maps, but I don't know how I could save data of every type to a map. For example there are eight Components bound to a System and everyone of them stores other data in the System. That could be a mesh, a list of meshes, a pointer to shader, just a bool flag, ... or all of these at the same time. – danijar Oct 17 '12 at 05:10
  • Here's a quick tutorial on unions: http://www.cplusplus.com/forum/beginner/15843/, but it looks like a void pointer is easier. – sampson-chen Oct 17 '12 at 05:13
  • as long as they're all objects, you should be able to distinguish them with `instanceof`. In all other cases, you'll have to hold the data type separately. This is a limitation of c++ – John Dvorak Oct 17 '12 at 05:13
  • They could be objects of my own classes, integers, strings, lists of anything, and so on. – danijar Oct 17 '12 at 05:15