This is how you never repeat data with boost:
Basically, the idea is to create a shared pointer for each individual resource item, use an ID to find the single shared pointer to the data, and instead of duplicating data we create a boost::weak_ptr and return it and boost pretty much handles all the cleanup for you.Code:#ifndef RESOURCE_MANAGER_H #define RESOURCE_MANAGER_H #include <vector> #include <map> #include <string> #include <boost\shared_ptr.hpp> #include <boost\weak_ptr.hpp> template< typename T_ > class Resource_Manager { public: typedef T_ value_type; // std library convention typedef boost::shared_ptr<T_> Resource_Ptr; typedef boost::weak_ptr<T_> Resource_Observer; typedef std::map< std::string, Resource_Ptr > Resource_Map; Resource_Manager<T_>() {}; ~Resource_Manager<T_>() {}; Resource_Observer Request_Resource(const std::string & name) { Resource_Map::iterator it = mResources.find(name); if (it == mResources.end()) { Resource_Ptr Raw_Resource(new T_); Raw_Resource->Load(name); mResources.insert(std::make_pair(name, Raw_Resource)); Resource_Observer Resource(Raw_Resource); return Resource; } else { return Resource_Observer(it->second); } } void Request_Resource_Removal(const std::string & name) { Resource_Map::iterator it = mResources.find(name); if (it != mResources.end()) { mResources.erase(it); } } private: Resource_Map mResources; }; #endif
Last edited by Shamino; 01-04-2008 at 01:06 PM.
Sometimes I forget what I am doing when I enter a room, actually, quite often.
Sometimes I forget what I am doing when I enter a room, actually, quite often.
Many libraries in boost are in almost standard. AFAIK the ptr containers library is not in the next standard, but it is still widely used and tested because it is a part of boost.
Switching to a ptr_vector is probably a better solution than creating your own version of it.
Another option is to change the class C to make copying less expensive. for example, if you only need to copy the class when it is inside the vector, then you can move its implementation into a single struct that is held via shared_ptr (another boost item that will be in the next standard). That way you don't have to change the syntax of when you use the vector, you only have to change the implementation of the particular class that is currently slow to copy.
Remember, though, that the solution above assumes the class won't break any other code if you switch to a shared implementation copy versus a cloned implementation copy.
Has different behaviour, though - an additional index check, and a throw if the check fails.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law
Which is a good thing.
If the index doesn't exist and you use [], you get undefined behavior (bad) or crash.
If the index doesn't exist when you use at, you get an exception. You can handle it and your program can correct the error and continue execution. Or you could just not handle the exception and then the program will crash or display a fancy error message and terminate.
GCC has the -D_GLIBCXX_DEBUG flag, which in particular causes [] to do bounds checking - see
http://gcc.gnu.org/onlinedocs/libstdc++/debug.html
so one can do a debug build with bounds checking, then recompile without the flag without changing the source later, which I prefer to using at(), the bounds checking of which can't be turned off. I don't know if other compilers have a similar feature.
Exactly as this book suggests: Use a checked STL implementation