All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
VectorMap.h
Go to the documentation of this file.
1 /// VectorMap
2 /// 17-Apr-2008 William Seligman <seligman@nevis.columbia.edu>
3 ///
4 /// This class is an implementation of a concept discussion in
5 /// "Effective STL" by Scott Meyers:
6 ///
7 /// STL maps are useful because their contents are always sorted, so
8 /// they're effective for fast searches. However, in almost every
9 /// other respect vectors are superior: They take up less space, and
10 /// they use random-access iterators.
11 ///
12 /// This class implements "sorted vector maps," that is, an STL-style
13 /// map implemented as a sorted STL vector of pairs. I've done my best
14 /// to implement all aspects of the std::map interface in this class,
15 /// with some additions; if you've defined the following:
16 ///
17 /// VectorMap<key_type, data_type> svm;
18 ///
19 /// - svm(i) will return the "i-th" value in the map; that is, "i" is a
20 /// numeric index instead of a key. (Note the use of parenthesis
21 /// instead of square brackets.) This is a boon to physicists, most
22 /// of whom couldn't tell an iterator from a hole in the wall.
23 ///
24 /// - svm.Key(i) will return the "i-th" key in the map.
25 ///
26 /// - svm.Data(i) will return the same result as svm(i).
27 ///
28 /// - svm[key_type] will now return the corresponding data_type in both
29 /// const and non-const contexts. However, if you ask for svm[key]
30 /// and the key isn't in the map, and you're in a const context, the
31 /// routine will throw an out-of-range exception.
32 ///
33 /// INCREDIBLY IMPORTANT NOTE: The "key type" of a VectorMap
34 /// cannot be a "const" type (unlike maps); it won't even compile.
35 /// When you do an insert, the underlying vector has to move things
36 /// around within its list, and it uses the assignment operator=() (or
37 /// "vector{i+1)=vector(i)" if you like). You can't do that if either
38 /// the key or the data is const.
39 ///
40 /// As with a map, there's no way to insert items at a specific
41 /// location in a VectorMap. The insertion methods (including
42 /// operator[]) all operate on a sorted sequence according to the key.
43 /// Because of this, insertions take a long time.
44 ///
45 /// However, for our processing, this doesn't matter much; for almost
46 /// all our maps, we typically have:
47 ///
48 /// - Initialization, where the time doesn't matter (e.g., tracks in a
49 /// Monte Carlo).
50 ///
51 /// - Access, where efficient or "simple" access to the map's contents
52 /// are important. In general, we access a map many, many more times
53 /// that we create one.
54 ///
55 /// - After we create/initialize a map, we never change its contents.
56 ///
57 /// For this usage, a sorted vector is generally superior to a map.
58 ///
59 /// This class just implements the equivalent of an STL map, not a
60 /// multimap, set, nor a multiset. If there's a need, I may create
61 /// additional classes.
62 ///
63 ///
64 /// Is there any map feature that's not implemented? Yes:
65 ///
66 /// - equal_range in a const context (which causes some weird ROOT
67 /// dictionary problem); this isn't likely to be used for a map
68 /// anyway (multimaps or multisets would be a different story).
69 ///
70 /// Advanced implementation note: Depending on the application, it
71 /// might be possible to speed up this class by using "lazy
72 /// evaluation"; that is, we wouldn't actually sort the vector until
73 /// the user actually tries to access its contents. I'm not going to
74 /// do this, because:
75 ///
76 /// A) I don't think my programming skills are up to the task.
77 ///
78 /// B) In the primary application for which I plan to use this class
79 /// (Monte-Carlo particle tracks), we're performing at least one
80 /// search after every insert; lazy evaluation wouldn't be much of a
81 /// speed improvement.
82 ///
83 /// Feb-2011 WGS: VectorMap mostly looks like a map, but there are some
84 /// memory-management issues that relate to it being a vector. Include
85 /// the vector-based routines reserve() and capacity().
86 
87 #ifndef Utilities_VectorMap_H
88 #define Utilities_VectorMap_H
89 
90 #include <cstddef>
91 #include <vector>
92 #include <map>
93 #include <functional>
94 #include <algorithm>
95 #include <stdexcept> // std::out_of_range
96 
97 namespace util {
98 
99  // Start with the same template terms as used for a map (copied from
100  // GNU C++'s stl_map.h). In general, if you see variables that begin
101  // with underscores ("_"), it means I copied the code directly from
102  // GNU C++, either from stl_map.h or stl_vector.h.
103  template < typename _Key, typename _Tp, typename _Compare = std::less<_Key> >
104  class VectorMap {
105  public:
106  // Define lots of handy types.
107 
108  typedef _Key key_type;
109  typedef _Tp mapped_type;
110  typedef std::pair<_Key, _Tp> value_type;
111  typedef _Compare key_compare;
112  typedef std::allocator< std::pair<_Key, _Tp> > allocator_type;
113 
114  typedef std::vector<value_type> vector_type;
115 
116  typedef typename vector_type::pointer pointer;
117  typedef typename vector_type::const_pointer const_pointer;
118  typedef typename vector_type::reference reference;
119  typedef typename vector_type::const_reference const_reference;
120  typedef typename vector_type::iterator iterator;
121  typedef typename vector_type::const_iterator const_iterator;
122  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
123  typedef std::reverse_iterator<iterator> reverse_iterator;
124  typedef size_t size_type;
125  typedef ptrdiff_t difference_type;
126 
127  public:
128 
129  // The "value_compare" class is an internal utility class for
130  // VectorMap. It extends the "_Compare" template entry (the
131  // name of a class that compares the keys) to a binary operator that
132  // compares two entries in the "sortedVectorMap" private member.
133 
134  // Note that because of the context-based multiple definitions of
135  // operator(), this class cannot inherit from the STL
136  // binary_function template. This means that it's not "adaptable";
137  // e.g., you can't use it as an argument to bind2nd.
138 
139  // If you're getting confused by all this, just think of it as a
140  // fancy way of defining "less than" and ignore it.
142  {
143  friend class VectorMap<_Key, _Tp, _Compare>;
144  protected:
145 
146  value_compare(_Compare __c = _Compare())
147  : comp(__c) { }
148  _Compare GetCompare() const { return comp; }
149  _Compare comp;
150 
151  public:
152 
153  // From an idea suggested by item 23 in "Effective STL" by Scott
154  // Meyers:
155  bool operator()(const value_type& __x,
156  const value_type& __y) const
157  { return keyLess(__x.first, __y.first); }
158  bool operator()(const value_type& __x,
159  const key_type& __y) const
160  { return keyLess(__x.first, __y); }
161  bool operator()(const key_type& __x,
162  const value_type& __y) const
163  { return keyLess(__x, __y.first); }
164  private:
165  bool keyLess(const key_type& __x,
166  const key_type& __y) const
167  { return comp(__x, __y); }
168  };
169 
170  private:
171  // The vector that contains the sorted pair<Key,Value> entries.
172  vector_type sortedVectorMap; // The sorted <key,data> pairs.
173 
174  // The actual key-comparison object.
175  value_compare valueCompare; //! Don't write this to the ROOT file.
176 
177  public:
178  // After copying a lot of stuff from GNU C++, here's where I start
179  // implementing some methods on my own. I'm trying to be complete,
180  // and implementing all the methods that STL map supports, even if I
181  // don't think I'll ever use them.
182 
184  {
185  return sortedVectorMap.get_allocator();
186  }
187 
189  {
190  return sortedVectorMap.begin();
191  }
192 
194  {
195  return sortedVectorMap.begin();
196  }
197 
199  {
200  return sortedVectorMap.end();
201  }
202 
204  {
205  return sortedVectorMap.end();
206  }
207 
209  {
210  return sortedVectorMap.rbegin();
211  }
212 
214  {
215  return sortedVectorMap.rbegin();
216  }
217 
219  {
220  return sortedVectorMap.rend();
221  }
222 
224  {
225  return sortedVectorMap.rend();
226  }
227 
228  bool empty() const
229  {
230  return sortedVectorMap.empty();
231  }
232 
233  size_t size() const
234  {
235  return sortedVectorMap.size();
236  }
237 
238  size_t max_size() const
239  {
240  return sortedVectorMap.max_size();
241  }
242 
244  {
245  // Do a binary search for the key.
246  iterator i = lower_bound(key);
247 
248  // If the key is not found, or i->first is less than key, then
249  // the key is not found.
250  if (i == end() || key_comp()(key, (*i).first))
251  // Insert this key into the map, with a default value. Thanks
252  // to the lower_bound call above, i already points to correct
253  // place to insert the value in the sorted vector.
254  i = sortedVectorMap.insert(i, value_type(key, mapped_type() ));
255 
256  return (*i).second;
257  }
258 
259  // Not part of STL, even in a GNU extension, but something I always
260  // wanted: operator[] in a const context. Derived from the at()
261  // method below.
262  const mapped_type& operator[](const key_type& __k) const
263  {
264  const_iterator __i = lower_bound(__k);
265  if (__i == end() || key_comp()(__k, (*__i).first))
266  throw std::out_of_range("Utilities/VectorMap::operator[]");
267  return (*__i).second;
268  }
269 
270  // at(), equivalent to operator[] except that it can throw an
271  // exception.
272  mapped_type& at(const key_type& __k)
273  {
274  iterator __i = lower_bound(__k);
275  if (__i == end() || key_comp()(__k, (*__i).first))
276  throw std::out_of_range("Utilities/VectorMap::at");
277  return (*__i).second;
278  }
279 
280  const mapped_type& at(const key_type& __k) const
281  {
282  const_iterator __i = lower_bound(__k);
283  if (__i == end() || key_comp()(__k, (*__i).first))
284  throw std::out_of_range("Utilities/VectorMap::at");
285  return (*__i).second;
286  }
287 
288  // One of the key members of this adapted class. Attempt to insert
289  // the entry (a pair<key,value>) into the map. Since this is a
290  // unique insert, the map will only be changed if the key is not
291  // already present. In the returned pair, the iterator points to
292  // the map entry that contains the key; the bool indicates whether
293  // the insertion succeeded or failed. Note the combination of a
294  // binary search (lower_bound) with an insert-in-the-middle
295  // ("sortedVectorMap.insert()"); that what's makes this method so
296  // slow.
297  std::pair<iterator,bool> insert(const value_type& entry)
298  {
299  const key_type& key = entry.first;
300  iterator i = lower_bound(key);
301  if (i == end() || key_comp()(key, (*i).first))
302  {
303  // The entry was not found. In that case, lower_bound has
304  // already found the correct point at which we want to insert
305  // the entry to maintain the sort.
306  i = sortedVectorMap.insert(i, entry);
307  return std::make_pair( i, true);
308  }
309 
310  // If we get here, the entry was found. Return failure.
311  return std::make_pair( i, false );
312  }
313 
314  // In this form of insert(), the iterator in the argument is
315  // supposed to give us a hint about where to insert the item.
316  // Actually, this hint is useless (since lower_bound doesn't take a
317  // hint <heh, heh>). So just do a regular insert instead.
319  {
320  std::pair<iterator,bool> result = insert(entry);
321  return result.first;
322  }
323 
324  // Mass insertion.
325  template <typename _InputIterator>
326  void insert(_InputIterator __first, _InputIterator __last)
327  {
328  for ( ; __first != __last; ++__first)
329  insert(*__first);
330  }
331 
332  void erase(iterator __position)
333  {
334  sortedVectorMap.erase(__position);
335  }
336 
337  // Erases all the entries with the key, and returns the number of
338  // erasures.
340  {
341  iterator i = find(key);
342  if ( i == end() ) return 0;
343  erase(i);
344  return 1;
345  }
346 
347  // Erase a range.
348  void erase(iterator __first, iterator __last)
349  {
350  sortedVectorMap.erase(__first, __last);
351  }
352 
353  // Swap two maps. For VectorMap, this is pretty simple: use
354  // the standard vector mechanism for swapping the vector portion of
355  // the maps, then swap the value_compare objects (if any) by the
356  // usual "temp" method.
357  void swap(VectorMap& other)
358  {
359  sortedVectorMap.swap(other.sortedVectorMap);
360  value_compare temp(valueCompare);
361  valueCompare = other.valueCompare;
362  other.valueCompare = temp;
363  }
364 
365  void clear()
366  {
367  sortedVectorMap.clear();
368  }
369 
370  // Returns the key-comparison object used for this VectorMap.
372  {
373  return valueCompare.GetCompare();
374  }
375 
376  // Returns the value-comparison object, which just compares the
377  // entry.first of the two pairs.
378  value_compare value_comp() const
379  {
380  return valueCompare;
381  }
382 
383  iterator find(const key_type& key)
384  {
385  iterator i = lower_bound(key);
386  if (i == end() || key_comp()(key, (*i).first))
387  return end();
388 
389  return i;
390  }
391 
392  const_iterator find(const key_type& key) const
393  {
394  const_iterator i = lower_bound(key);
395  if (i == end() || key_comp()(key, (*i).first))
396  return end();
397 
398  return i;
399  }
400 
401  // Count the number of entries with a given key (which will be 0 or
402  // 1 for a map).
403  size_type count(const key_type& __x) const
404  {
405  return find(__x) == end() ? 0 : 1;
406  }
407 
409  {
410  return std::lower_bound(begin(),end(),__x,valueCompare);
411  }
412 
414  {
415  return std::lower_bound(begin(),end(),__x,valueCompare);
416  }
417 
419  {
420  return std::upper_bound(begin(),end(),__x,valueCompare);
421  }
422 
424  {
425  return std::upper_bound(begin(),end(),__x,valueCompare);
426  }
427 
428  std::pair<iterator, iterator> equal_range(const key_type& key)
429  {
430  return std::equal_range(begin(),end(),key,valueCompare);
431  }
432 
433  // The following code does not compile when processed by ROOT's
434  // dictionary. For now, this is not a big deal; no one is likely to
435  // use equal_range on a map anyway. If we ever have to implement a
436  // multimap or multiset using the same scheme, this could be a
437  // problem.
438  /*
439  std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
440  {
441  return std::equal_range(begin(),end(),key,valueCompare);
442  }
443  */
444 
445  // My own little extras, as described near the top of this header
446  // file's comments:
447 
448  const mapped_type& operator()(const size_type& index) const
449  {
450  return sortedVectorMap[index].second;
451  }
452 
453  const mapped_type& Data(const size_type& index) const
454  {
455  return sortedVectorMap[index].second;
456  }
457 
458  const key_type& Key(const size_type& index) const
459  {
460  return sortedVectorMap[index].first;
461  }
462 
463 
464  // Vector-based memory management.
465  void reserve( size_type i )
466  {
467  sortedVectorMap.reserve(i);
468  }
470  {
471  return sortedVectorMap.capacity();
472  }
473 
474 
475  // Friend definitions for comparison operators.
476  template <typename _K1, typename _T1, typename _C1>
477  friend bool operator== (const VectorMap<_K1, _T1, _C1>&,
478  const VectorMap<_K1, _T1, _C1>&);
479 
480  template <typename _K1, typename _T1, typename _C1>
481  friend bool operator< (const VectorMap<_K1, _T1, _C1>&,
482  const VectorMap<_K1, _T1, _C1>&);
483 
484  public:
485 
486  };
487 
488 } // namespace util
489 
490 namespace util {
491 
492  // Comparison operators.
493  template <typename _Key, typename _Tp, typename _Compare>
496  {
497  return __x.sortedVectorMap == __y.sortedVectorMap;
498  }
499 
500  template <typename _Key, typename _Tp, typename _Compare>
501  inline bool operator<(const VectorMap<_Key, _Tp, _Compare>& __x,
503  {
504  return std::lexicographical_compare(__x.sortedVectorMap.begin(),
505  __x.sortedVectorMap.end(),
506  __y.sortedVectorMap.begin(),
507  __y.sortedVectorMap.end(),
508  __x.valueCompare);
509  }
510 
511  /// Based on operator==
512  template <typename _Key, typename _Tp, typename _Compare>
515  {
516  return !(__x == __y);
517  }
518 
519  /// Based on operator<
520  template <typename _Key, typename _Tp, typename _Compare>
523  {
524  return __y < __x;
525  }
526 
527  /// Based on operator<
528  template <typename _Key, typename _Tp, typename _Compare>
529  inline bool operator<=(const VectorMap<_Key, _Tp, _Compare>& __x,
531  {
532  return !(__y < __x);
533  }
534 
535  /// Based on operator<
536  template <typename _Key, typename _Tp, typename _Compare>
539  {
540  return !(__x < __y);
541  }
542 
543  /// See VectorMap::swap().
544  template <typename _Key, typename _Tp, typename _Compare>
547  {
548  __x.swap(__y);
549  }
550 
551 } // namespace util
552 
553 #endif // Utilities_VectorMap_H
std::pair< iterator, iterator > equal_range(const key_type &key)
Definition: VectorMap.h:428
iterator end()
Definition: VectorMap.h:198
const_reverse_iterator rend() const
Definition: VectorMap.h:223
void reserve(size_type i)
Definition: VectorMap.h:465
bool operator==(TensorIndices< RANK1 > const &a, TensorIndices< RANK2 > const &b)
Comparison operator with tensors of different rank.
_Compare key_compare
Definition: VectorMap.h:111
value_compare value_comp() const
Definition: VectorMap.h:378
const mapped_type & operator()(const size_type &index) const
Definition: VectorMap.h:448
size_t size_type
Definition: VectorMap.h:124
void erase(iterator __first, iterator __last)
Definition: VectorMap.h:348
reverse_iterator rbegin()
Definition: VectorMap.h:208
const_iterator upper_bound(const key_type &__x) const
Definition: VectorMap.h:423
const_reverse_iterator rbegin() const
Definition: VectorMap.h:213
value_compare valueCompare
Definition: VectorMap.h:175
const_iterator begin() const
Definition: VectorMap.h:193
mapped_type & at(const key_type &__k)
Definition: VectorMap.h:272
const mapped_type & Data(const size_type &index) const
Definition: VectorMap.h:453
size_t max_size() const
Definition: VectorMap.h:238
reverse_iterator rend()
Definition: VectorMap.h:218
void insert(_InputIterator __first, _InputIterator __last)
Definition: VectorMap.h:326
bool operator()(const value_type &__x, const value_type &__y) const
Definition: VectorMap.h:155
vector_type::iterator iterator
Definition: VectorMap.h:120
std::pair< iterator, bool > insert(const value_type &entry)
Definition: VectorMap.h:297
void erase(iterator __position)
Definition: VectorMap.h:332
vector_type sortedVectorMap
Definition: VectorMap.h:172
iterator begin()
Definition: VectorMap.h:188
const mapped_type & operator[](const key_type &__k) const
Definition: VectorMap.h:262
size_t size() const
Definition: VectorMap.h:233
std::allocator< std::pair< _Key, _Tp > > allocator_type
Definition: VectorMap.h:112
const mapped_type & at(const key_type &__k) const
Definition: VectorMap.h:280
vector_type::const_iterator const_iterator
Definition: VectorMap.h:121
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: VectorMap.h:122
size_type capacity()
Definition: VectorMap.h:469
bool empty() const
Definition: VectorMap.h:228
bool operator()(const key_type &__x, const value_type &__y) const
Definition: VectorMap.h:161
iterator insert(iterator, const value_type &entry)
Definition: VectorMap.h:318
vector_type::const_pointer const_pointer
Definition: VectorMap.h:117
allocator_type get_allocator() const
Don&#39;t write this to the ROOT file.
Definition: VectorMap.h:183
const key_type & Key(const size_type &index) const
Definition: VectorMap.h:458
std::reverse_iterator< iterator > reverse_iterator
Definition: VectorMap.h:123
const_iterator find(const key_type &key) const
Definition: VectorMap.h:392
iterator find(const key_type &key)
Definition: VectorMap.h:383
iterator lower_bound(const key_type &__x)
Definition: VectorMap.h:408
void swap(VectorMap< _Key, _Tp, _Compare > &__x, VectorMap< _Key, _Tp, _Compare > &__y)
See VectorMap::swap().
Definition: VectorMap.h:545
vector_type::reference reference
Definition: VectorMap.h:118
key_compare key_comp() const
Definition: VectorMap.h:371
mapped_type & operator[](const key_type &key)
Definition: VectorMap.h:243
ptrdiff_t difference_type
Definition: VectorMap.h:125
size_type erase(const key_type &key)
Definition: VectorMap.h:339
size_type count(const key_type &__x) const
Definition: VectorMap.h:403
bool operator()(const value_type &__x, const key_type &__y) const
Definition: VectorMap.h:158
void swap(VectorMap &other)
Definition: VectorMap.h:357
friend bool operator==(const VectorMap< _K1, _T1, _C1 > &, const VectorMap< _K1, _T1, _C1 > &)
iterator upper_bound(const key_type &__x)
Definition: VectorMap.h:418
vector_type::const_reference const_reference
Definition: VectorMap.h:119
bool operator>(const VectorMap< _Key, _Tp, _Compare > &__x, const VectorMap< _Key, _Tp, _Compare > &__y)
Based on operator&lt;.
Definition: VectorMap.h:521
std::vector< value_type > vector_type
Definition: VectorMap.h:114
vector_type::pointer pointer
Definition: VectorMap.h:116
bool operator!=(TensorIndices< RANK1 > const &a, TensorIndices< RANK2 > const &b)
Comparison operator with tensors of different rank.
std::pair< _Key, _Tp > value_type
Definition: VectorMap.h:110
const_iterator lower_bound(const key_type &__x) const
Definition: VectorMap.h:413
const_iterator end() const
Definition: VectorMap.h:203
bool operator>=(const VectorMap< _Key, _Tp, _Compare > &__x, const VectorMap< _Key, _Tp, _Compare > &__y)
Based on operator&lt;.
Definition: VectorMap.h:537
bool keyLess(const key_type &__x, const key_type &__y) const
Definition: VectorMap.h:165