00001 00012 #ifndef UNIQUE_STORAGE_H 00013 #define UNIQUE_STORAGE_H 00014 00015 #include <vector> 00016 #include <map> 00017 #include <stdexcept> 00018 00033 template <typename I, typename V> class unique_storage { 00034 00035 public: 00036 unique_storage() { 00037 // id 0 00038 values.push_back(V()); 00039 } 00040 00041 virtual ~unique_storage() {} 00042 00043 typedef std::vector<V> stored_values; 00044 00046 struct id_value { 00048 id_value() : id(0) {} 00049 00051 bool set() const { 00052 return id; 00053 } 00054 00055 bool operator<(id_value const & rhs) const { 00056 return id < rhs.id; 00057 } 00058 00059 bool operator==(id_value const & rhs) const { 00060 return id == rhs.id; 00061 } 00062 00063 bool operator!=(id_value const & rhs) const { 00064 return !(id == rhs.id); 00065 } 00066 00067 private: 00068 friend class unique_storage<I, V>; 00069 00070 typedef typename stored_values::size_type size_type; 00071 00072 explicit id_value(size_type s) : id(s) {} 00073 00075 size_type id; 00076 }; 00077 00078 00080 id_value const create(V const & value) { 00081 typename id_map::value_type val(value, id_value(values.size())); 00082 std::pair<typename id_map::iterator, bool> 00083 inserted = ids.insert(val); 00084 if (inserted.second) 00085 values.push_back(value); 00086 00087 return inserted.first->second; 00088 } 00089 00090 00092 V const & get(id_value const & id) const { 00093 // some stl lack at(), so we emulate it 00094 if (id.id < values.size()) 00095 return values[id.id]; 00096 00097 throw std::out_of_range("unique_storage::get(): out of bounds"); 00098 } 00099 00100 private: 00101 typedef std::map<V, id_value> id_map; 00102 00104 stored_values values; 00105 00107 id_map ids; 00108 }; 00109 00110 #endif /* !UNIQUE_STORAGE_H */