lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
accumulation_map.h
00001 /*****************************************************/
00002 /* lean Containers              (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_CONTAINERS_ACCUMULATION_MAP
00006 #define LEAN_CONTAINERS_ACCUMULATION_MAP
00007 
00008 #include "../lean.h"
00009 #include <utility>
00010 
00011 namespace lean
00012 {
00013 namespace containers
00014 {
00015     
00017 
00021 template <class Container>
00022 class accumulation_map
00023 {
00024 public:
00026     typedef Container container_type;
00028     typedef typename container_type::allocator_type allocator_type;
00030     typedef typename container_type::size_type size_type;
00032     typedef typename container_type::difference_type difference_type;
00033 
00035     typedef typename container_type::pointer pointer;
00037     typedef typename container_type::const_pointer const_pointer;
00039     typedef typename container_type::reference reference;
00041     typedef typename container_type::const_reference const_reference;
00043     typedef typename container_type::value_type value_type;
00044 
00046     typedef typename container_type::iterator iterator;
00048     typedef typename container_type::const_iterator const_iterator;
00049 
00051     typedef typename container_type::reverse_iterator reverse_iterator;
00053     typedef typename container_type::const_reverse_iterator const_reverse_iterator;
00054 
00056     typedef typename container_type::key_compare key_compare;
00058     typedef typename container_type::key_type key_type;
00060     typedef typename container_type::mapped_type mapped_type;
00062     typedef typename container_type::value_compare value_compare;
00063 
00064 private:
00065     // Container
00066     container_type m_container;
00067 
00068     // Invalid marker
00069     mapped_type m_invalidValue;
00070 
00072     LEAN_INLINE void invalidate(mapped_type &value) const
00073     {
00074         // Const method modifier makes m_invalidValue const
00075         value = m_invalidValue;
00076     }
00077 
00078 public:
00080     accumulation_map() { }
00082     explicit accumulation_map(const key_compare& predicate)
00083         : m_container(predicate) { }
00085     accumulation_map(const key_compare& predicate, const allocator_type& allocator)
00086         : m_container(predicate, allocator) { }
00088     accumulation_map(const accumulation_map& right)
00089         : m_container(right.m_container) { }
00090 #ifndef LEAN0X_NO_RVALUE_REFERENCES
00091 
00092     accumulation_map(accumulation_map&& right)
00093         : m_container(std::move(right.m_container)) { }
00094 #endif
00095 
00096     template<class Iterator>
00097     accumulation_map(Iterator itFirst, Iterator itEnd)
00098         : m_container(itFirst, itEnd) { }
00100     template<class Iterator>
00101     accumulation_map(Iterator itFirst, Iterator itEnd, const key_compare& predicate)
00102         : m_container(itFirst, itEnd, predicate) { }
00104     template<class Iterator>
00105     accumulation_map(Iterator itFirst, Iterator itEnd, const key_compare& predicate, const allocator_type& allocator)
00106         : m_container(itFirst, itEnd, predicate, allocator) { }
00107 
00109     accumulation_map& operator =(const accumulation_map &right)
00110     {
00111         if (this != &right)
00112         {
00113             m_invalidValue = right.m_invalidValue;
00114 
00115             key_compare keyComp = m_container.key_comp();
00116 
00117             iterator itDest = m_container.begin();
00118             const_iterator itSource = right.begin();
00119 
00120             while (itSource != right.end() && itDest != m_container.end())
00121             {
00122                 // Replace old value with new one on exact match
00123                 if (itSource->first == itDest->first)
00124                     (itDest++)->second = (itSource++)->second;
00125                 // Wait for next source element, if still less than dest
00126                 else if (keyComp(itSource->first, itDest->first))
00127                     m_container.insert(itDest, *(itSource++));
00128                 // Source element already greater than dest, invalidate dest
00129                 else
00130                     invalidate((itDest++)->second);
00131             }
00132 
00133             // Invalidate remaining old elements
00134             while (itDest != m_container.end())
00135                 invalidate((itDest++)->second);
00136 
00137             // Append remaining source elements
00138             while (itSource != right.end())
00139                 m_container.insert(m_container.end(), *(itSource++));
00140         }
00141         return *this;
00142     }
00143 #ifndef LEAN0X_NO_RVALUE_REFERENCES
00144 
00145     inline accumulation_map& operator =(accumulation_map &&right)
00146     {
00147         m_container = std::move(right.m_container);
00148         return *this;
00149     }
00150 #endif
00151 
00153     LEAN_INLINE void inv_elem(const mapped_type &invalid) { m_invalidValue = invalid; }
00155     LEAN_INLINE mapped_type inv_elem(void) { return m_invalidValue; }
00156 
00158     LEAN_INLINE size_type size(void) const { return m_container.size(); };
00160     LEAN_INLINE bool empty(void) const { return m_container.empty(); };
00161 
00163     LEAN_INLINE std::pair<iterator, bool> insert(const value_type &element) { return m_container.insert(element); }
00165     LEAN_INLINE iterator insert(iterator itWhere, const value_type &element) { return m_container.insert(itWhere, element); }
00166 #ifndef LEAN0X_NO_RVALUE_REFERENCES
00167 
00168     LEAN_INLINE std::pair<iterator, bool> insert(value_type &&element) { return m_container.insert(std::move(element)); }
00170     LEAN_INLINE iterator insert(iterator itWhere, value_type &&element) { return m_container.insert(itWhere, std::move(element)); }
00171 #endif
00172 
00173     template<class Iterator>
00174     LEAN_INLINE void insert(Iterator itFirst, Iterator itEnd) { m_container.insert(itFirst, itEnd); }
00175 
00177     LEAN_INLINE size_type erase(const key_type &key)
00178     {
00179         iterator itElem = m_container.find(key);
00180 
00181         if (itElem != m_container.end())
00182         {
00183             invalidate(itElem->second);
00184             return 1;
00185         }
00186         else
00187             return 0;
00188     }
00190     LEAN_INLINE iterator erase(iterator itWhere)
00191     {
00192         invalidate(itWhere->second);
00193         return itWhere;
00194     }
00196     LEAN_INLINE void erase(iterator itFirst, iterator itEnd)
00197     {
00198         while (itFirst != itEnd)
00199             invalidate((itFirst++)->second);
00200     }
00201 
00203     LEAN_INLINE size_type erase_fully(const key_type &key) { return m_container.erase(key); }
00205     LEAN_INLINE iterator erase_fully(iterator itWhere) { return m_container.erase(itWhere); }
00207     LEAN_INLINE void erase_fully(iterator itFirst, iterator itEnd) { m_container.erase(itFirst, itEnd); }
00208 
00210     LEAN_INLINE void clear(void)
00211     {
00212         // Invalidate all elements
00213         for (iterator itElem = begin(); itElem != end(); ++itElem)
00214             invalidate(itElem->second);
00215     }
00217     LEAN_INLINE void reset(void) { m_container.clear(); }
00218 
00220     LEAN_INLINE key_compare key_comp(void) const { return m_container.key_comp(); }
00222     LEAN_INLINE value_compare value_comp(void) const { return m_container.value_comp(); }
00223 
00225     LEAN_INLINE allocator_type get_allocator() const { return m_container.get_allocator(); }
00227     LEAN_INLINE size_type max_size(void) const { return m_container.max_size(); }
00228 
00230     LEAN_INLINE iterator lower_bound(const key_type &key) { return m_container.lower_bound(key); }
00232     LEAN_INLINE const_iterator lower_bound(const key_type &key) const { return m_container.lower_bound(key); }
00234     LEAN_INLINE iterator upper_bound(const key_type &key) { return m_container.upper_bound(key); }
00236     LEAN_INLINE const_iterator upper_bound(const key_type &key) const { return m_container.upper_bound(key); }
00238     LEAN_INLINE std::pair<iterator, iterator> equal_range(const key_type &key) { return m_container.equal_range(key); }
00240     LEAN_INLINE std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const { return m_container.equal_range(key); }
00241 
00243     LEAN_INLINE iterator find(const key_type &key) { return m_container.find(key); }
00245     LEAN_INLINE const_iterator find(const key_type &key) const { return m_container.find(key); }
00247     LEAN_INLINE size_type count(const key_type &key) const { return m_container.count(key); }
00248 
00250     LEAN_INLINE mapped_type& operator [](const key_type &key) { return m_container[key]; }
00251 
00253     LEAN_INLINE iterator begin(void) { return m_container.begin(); }
00255     LEAN_INLINE const_iterator begin(void) const { return m_container.begin(); }
00257     LEAN_INLINE iterator end(void) { return m_container.end(); }
00259     LEAN_INLINE const_iterator end(void) const { return m_container.end(); }
00260 
00262     LEAN_INLINE reverse_iterator rbegin(void) { return m_container.rbegin(); }
00264     LEAN_INLINE const_reverse_iterator rbegin(void) const { return m_container.rbegin(); }
00266     LEAN_INLINE reverse_iterator rend(void) { return m_container.rend(); }
00268     LEAN_INLINE const_reverse_iterator rend(void) const { return m_container.rend(); }
00269 
00270     // Swaps the elements of two accumulation maps.
00271     LEAN_INLINE void swap(accumulation_map& right)
00272     {
00273         using std::swap;
00274 
00275         swap(m_container, right.m_container);
00276     }
00277 };
00278 
00279 // Swaps the elements of two accumulation maps.
00280 template<class Container>
00281 LEAN_INLINE void swap(accumulation_map<Container>& left, accumulation_map<Container>& right)
00282 {
00283     left.swap(right);
00284 }
00285 
00286 } // namespace
00287 
00288 using containers::accumulation_map;
00289 
00290 } // namespace
00291 
00292 #endif