Ah, i see what you mean.
Nothing to do with multithreading.gDefaultDataStoreSize = 1; //This is probably a const global, but assume that it's one for this example const int & from_state( State<int>(10) ).as<int>(); auto state2( State<int>(20) ); //causes Datastore::_data to resize use(from_state);//uses freed memory.That's a quick and dirty example, and you can imagine that generally from_state would be a parameter to a function up the tree, in unrelated code.
Thing is, i really don't pass the underlying ints/float/whathaveyou as references, but pass the State object directly, either by reference or by value, as copying it is just a copy of 1 int, 2 pointers, and a call to a virtual method to increase/decrease the reference counts, and when i need to change the underlying data, i use
someState.as<int>() = anotherValue;
So it's always just a one liner. However, seeing as i can't control it (i can control myself, but not some other guy who would do like you wrote), i have 2 options: change the container from vector to deque like you said, or maybe change the access rules for the State object, to it has 2 methods, one for getting a copy of the data, and another to set a new value (T get<T>() and void set<T>(const T& newVal) ), however, then i'm locking myself to using cheaply copyable data types (cant use a class that contains other classes itself, or containers and such). So i guess deque is the best option here. Thanks for the feedback!
I'm gonna try using typeid then, unless someone can point out why i shouldn't, or proposes a better method. Thinking of using the hash_code it returns (c++11 feature), but i guess it doesn't matter much.
If you don't check, then as long as you never do the wrong call, everything is fine. If you ever do use the wrong call, it could be hard to track down the error. I suggest putting the check in an assert.
Yeah saving the typeid seems like a much better approach to a check.
So, the problems mentioned:
Access to states would be quite slow (map query) - using a typeid check is better
All the constructors are called up front, and destructors are never called until the store is shut down - maybe call the destructor manually when the reference count gets to 0 for a slot?
Once allocated, memory can only be reused for the same type as the original allocation - that's the idea, actually, as the purpose for DataStore<T> is to be an object pool of sorts. Am i doing something wrong with the implementation for this to be a problem, and not a feature?
No way to break circular references - not sure what this is referring to
I don't believe this can be made thread safe - could it be made thread safe by somehow atomizing the retrieval operation of the data store? Or is the problem bigger than that?
Again, thanks for the help!