LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
VectorMap.h
Go to the documentation of this file.
1 
87 #ifndef Utilities_VectorMap_H
88 #define Utilities_VectorMap_H
89 
90 #include <algorithm>
91 #include <cstddef>
92 #include <functional>
93 #include <map>
94 #include <stdexcept> // std::out_of_range
95 #include <vector>
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;
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  // The "value_compare" class is an internal utility class for
129  // VectorMap. It extends the "_Compare" template entry (the
130  // name of a class that compares the keys) to a binary operator that
131  // compares two entries in the "sortedVectorMap" private member.
132 
133  // Note that because of the context-based multiple definitions of
134  // operator(), this class cannot inherit from the STL
135  // binary_function template. This means that it's not "adaptable";
136  // e.g., you can't use it as an argument to bind2nd.
137 
138  // If you're getting confused by all this, just think of it as a
139  // fancy way of defining "less than" and ignore it.
141  friend class VectorMap<_Key, _Tp, _Compare>;
142 
143  protected:
144  value_compare(_Compare __c = _Compare()) : comp(__c) {}
145  _Compare GetCompare() const { return comp; }
146  _Compare comp;
147 
148  public:
149  // From an idea suggested by item 23 in "Effective STL" by Scott
150  // Meyers:
151  bool operator()(const value_type& __x, const value_type& __y) const
152  {
153  return keyLess(__x.first, __y.first);
154  }
155  bool operator()(const value_type& __x, const key_type& __y) const
156  {
157  return keyLess(__x.first, __y);
158  }
159  bool operator()(const key_type& __x, const value_type& __y) const
160  {
161  return keyLess(__x, __y.first);
162  }
163 
164  private:
165  bool keyLess(const key_type& __x, const key_type& __y) const { return comp(__x, __y); }
166  };
167 
168  private:
169  // The vector that contains the sorted pair<Key,Value> entries.
170  vector_type sortedVectorMap; // The sorted <key,data> pairs.
171 
172  // The actual key-comparison object.
174 
175  public:
176  // After copying a lot of stuff from GNU C++, here's where I start
177  // implementing some methods on my own. I'm trying to be complete,
178  // and implementing all the methods that STL map supports, even if I
179  // don't think I'll ever use them.
180 
181  allocator_type get_allocator() const { return sortedVectorMap.get_allocator(); }
182 
183  iterator begin() { return sortedVectorMap.begin(); }
184 
185  const_iterator begin() const { return sortedVectorMap.begin(); }
186 
187  iterator end() { return sortedVectorMap.end(); }
188 
189  const_iterator end() const { return sortedVectorMap.end(); }
190 
191  reverse_iterator rbegin() { return sortedVectorMap.rbegin(); }
192 
193  const_reverse_iterator rbegin() const { return sortedVectorMap.rbegin(); }
194 
195  reverse_iterator rend() { return sortedVectorMap.rend(); }
196 
197  const_reverse_iterator rend() const { return sortedVectorMap.rend(); }
198 
199  bool empty() const { return sortedVectorMap.empty(); }
200 
201  size_t size() const { return sortedVectorMap.size(); }
202 
203  size_t max_size() const { return sortedVectorMap.max_size(); }
204 
205  mapped_type& operator[](const key_type& key)
206  {
207  // Do a binary search for the key.
208  iterator i = lower_bound(key);
209 
210  // If the key is not found, or i->first is less than key, then
211  // the key is not found.
212  if (i == end() || key_comp()(key, (*i).first))
213  // Insert this key into the map, with a default value. Thanks
214  // to the lower_bound call above, i already points to correct
215  // place to insert the value in the sorted vector.
216  i = sortedVectorMap.insert(i, value_type(key, mapped_type()));
217 
218  return (*i).second;
219  }
220 
221  // Not part of STL, even in a GNU extension, but something I always
222  // wanted: operator[] in a const context. Derived from the at()
223  // method below.
224  const mapped_type& operator[](const key_type& __k) const
225  {
226  const_iterator __i = lower_bound(__k);
227  if (__i == end() || key_comp()(__k, (*__i).first))
228  throw std::out_of_range("Utilities/VectorMap::operator[]");
229  return (*__i).second;
230  }
231 
232  // at(), equivalent to operator[] except that it can throw an
233  // exception.
234  mapped_type& at(const key_type& __k)
235  {
236  iterator __i = lower_bound(__k);
237  if (__i == end() || key_comp()(__k, (*__i).first))
238  throw std::out_of_range("Utilities/VectorMap::at");
239  return (*__i).second;
240  }
241 
242  const mapped_type& at(const key_type& __k) const
243  {
244  const_iterator __i = lower_bound(__k);
245  if (__i == end() || key_comp()(__k, (*__i).first))
246  throw std::out_of_range("Utilities/VectorMap::at");
247  return (*__i).second;
248  }
249 
250  // One of the key members of this adapted class. Attempt to insert
251  // the entry (a pair<key,value>) into the map. Since this is a
252  // unique insert, the map will only be changed if the key is not
253  // already present. In the returned pair, the iterator points to
254  // the map entry that contains the key; the bool indicates whether
255  // the insertion succeeded or failed. Note the combination of a
256  // binary search (lower_bound) with an insert-in-the-middle
257  // ("sortedVectorMap.insert()"); that what's makes this method so
258  // slow.
259  std::pair<iterator, bool> insert(const value_type& entry)
260  {
261  const key_type& key = entry.first;
262  iterator i = lower_bound(key);
263  if (i == end() || key_comp()(key, (*i).first)) {
264  // The entry was not found. In that case, lower_bound has
265  // already found the correct point at which we want to insert
266  // the entry to maintain the sort.
267  i = sortedVectorMap.insert(i, entry);
268  return std::make_pair(i, true);
269  }
270 
271  // If we get here, the entry was found. Return failure.
272  return std::make_pair(i, false);
273  }
274 
275  // In this form of insert(), the iterator in the argument is
276  // supposed to give us a hint about where to insert the item.
277  // Actually, this hint is useless (since lower_bound doesn't take a
278  // hint <heh, heh>). So just do a regular insert instead.
279  iterator insert(iterator, const value_type& entry)
280  {
281  std::pair<iterator, bool> result = insert(entry);
282  return result.first;
283  }
284 
285  // Mass insertion.
286  template <typename _InputIterator>
287  void insert(_InputIterator __first, _InputIterator __last)
288  {
289  for (; __first != __last; ++__first)
290  insert(*__first);
291  }
292 
293  void erase(iterator __position) { sortedVectorMap.erase(__position); }
294 
295  // Erases all the entries with the key, and returns the number of
296  // erasures.
297  size_type erase(const key_type& key)
298  {
299  iterator i = find(key);
300  if (i == end()) return 0;
301  erase(i);
302  return 1;
303  }
304 
305  // Erase a range.
306  void erase(iterator __first, iterator __last) { sortedVectorMap.erase(__first, __last); }
307 
308  // Swap two maps. For VectorMap, this is pretty simple: use
309  // the standard vector mechanism for swapping the vector portion of
310  // the maps, then swap the value_compare objects (if any) by the
311  // usual "temp" method.
313  {
314  sortedVectorMap.swap(other.sortedVectorMap);
315  value_compare temp(valueCompare);
316  valueCompare = other.valueCompare;
317  other.valueCompare = temp;
318  }
319 
320  void clear() { sortedVectorMap.clear(); }
321 
322  // Returns the key-comparison object used for this VectorMap.
323  key_compare key_comp() const { return valueCompare.GetCompare(); }
324 
325  // Returns the value-comparison object, which just compares the
326  // entry.first of the two pairs.
328 
329  iterator find(const key_type& key)
330  {
331  iterator i = lower_bound(key);
332  if (i == end() || key_comp()(key, (*i).first)) return end();
333 
334  return i;
335  }
336 
337  const_iterator find(const key_type& key) const
338  {
339  const_iterator i = lower_bound(key);
340  if (i == end() || key_comp()(key, (*i).first)) return end();
341 
342  return i;
343  }
344 
345  // Count the number of entries with a given key (which will be 0 or
346  // 1 for a map).
347  size_type count(const key_type& __x) const { return find(__x) == end() ? 0 : 1; }
348 
349  iterator lower_bound(const key_type& __x)
350  {
351  return std::lower_bound(begin(), end(), __x, valueCompare);
352  }
353 
354  const_iterator lower_bound(const key_type& __x) const
355  {
356  return std::lower_bound(begin(), end(), __x, valueCompare);
357  }
358 
359  iterator upper_bound(const key_type& __x)
360  {
361  return std::upper_bound(begin(), end(), __x, valueCompare);
362  }
363 
364  const_iterator upper_bound(const key_type& __x) const
365  {
366  return std::upper_bound(begin(), end(), __x, valueCompare);
367  }
368 
369  std::pair<iterator, iterator> equal_range(const key_type& key)
370  {
371  return std::equal_range(begin(), end(), key, valueCompare);
372  }
373 
374  // The following code does not compile when processed by ROOT's
375  // dictionary. For now, this is not a big deal; no one is likely to
376  // use equal_range on a map anyway. If we ever have to implement a
377  // multimap or multiset using the same scheme, this could be a
378  // problem.
379  /*
380  std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const
381  {
382  return std::equal_range(begin(),end(),key,valueCompare);
383  }
384  */
385 
386  // My own little extras, as described near the top of this header
387  // file's comments:
388 
389  const mapped_type& operator()(const size_type& index) const
390  {
391  return sortedVectorMap[index].second;
392  }
393 
394  const mapped_type& Data(const size_type& index) const { return sortedVectorMap[index].second; }
395 
396  const key_type& Key(const size_type& index) const { return sortedVectorMap[index].first; }
397 
398  // Vector-based memory management.
399  void reserve(size_type i) { sortedVectorMap.reserve(i); }
400  size_type capacity() { return sortedVectorMap.capacity(); }
401 
402  // Friend definitions for comparison operators.
403  template <typename _K1, typename _T1, typename _C1>
405 
406  template <typename _K1, typename _T1, typename _C1>
407  friend bool operator<(const VectorMap<_K1, _T1, _C1>&, const VectorMap<_K1, _T1, _C1>&);
408 
409  public:
410  };
411 
412 } // namespace util
413 
414 namespace util {
415 
416  // Comparison operators.
417  template <typename _Key, typename _Tp, typename _Compare>
420  {
421  return __x.sortedVectorMap == __y.sortedVectorMap;
422  }
423 
424  template <typename _Key, typename _Tp, typename _Compare>
425  inline bool operator<(const VectorMap<_Key, _Tp, _Compare>& __x,
427  {
428  return std::lexicographical_compare(__x.sortedVectorMap.begin(),
429  __x.sortedVectorMap.end(),
430  __y.sortedVectorMap.begin(),
431  __y.sortedVectorMap.end(),
432  __x.valueCompare);
433  }
434 
436  template <typename _Key, typename _Tp, typename _Compare>
439  {
440  return !(__x == __y);
441  }
442 
444  template <typename _Key, typename _Tp, typename _Compare>
447  {
448  return __y < __x;
449  }
450 
452  template <typename _Key, typename _Tp, typename _Compare>
453  inline bool operator<=(const VectorMap<_Key, _Tp, _Compare>& __x,
455  {
456  return !(__y < __x);
457  }
458 
460  template <typename _Key, typename _Tp, typename _Compare>
463  {
464  return !(__x < __y);
465  }
466 
468  template <typename _Key, typename _Tp, typename _Compare>
470  {
471  __x.swap(__y);
472  }
473 
474 } // namespace util
475 
476 #endif // Utilities_VectorMap_H
std::pair< iterator, iterator > equal_range(const key_type &key)
Definition: VectorMap.h:369
intermediate_table::iterator iterator
std::allocator< std::pair< _Key, _Tp > > allocator_type
Definition: VectorMap.h:112
iterator end()
Definition: VectorMap.h:187
const_reverse_iterator rend() const
Definition: VectorMap.h:197
void reserve(size_type i)
Definition: VectorMap.h:399
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:26
_Compare key_compare
Definition: VectorMap.h:111
value_compare value_comp() const
Definition: VectorMap.h:327
const mapped_type & operator()(const size_type &index) const
Definition: VectorMap.h:389
_Compare GetCompare() const
Definition: VectorMap.h:145
size_t size_type
Definition: VectorMap.h:124
void erase(iterator __first, iterator __last)
Definition: VectorMap.h:306
reverse_iterator rbegin()
Definition: VectorMap.h:191
const_iterator upper_bound(const key_type &__x) const
Definition: VectorMap.h:364
const_reverse_iterator rbegin() const
Definition: VectorMap.h:193
value_compare valueCompare
Definition: VectorMap.h:173
const_iterator begin() const
Definition: VectorMap.h:185
mapped_type & at(const key_type &__k)
Definition: VectorMap.h:234
const mapped_type & Data(const size_type &index) const
Definition: VectorMap.h:394
size_t max_size() const
Definition: VectorMap.h:203
intermediate_table::const_iterator const_iterator
reverse_iterator rend()
Definition: VectorMap.h:195
void insert(_InputIterator __first, _InputIterator __last)
Definition: VectorMap.h:287
bool operator()(const value_type &__x, const value_type &__y) const
Definition: VectorMap.h:151
vector_type::iterator iterator
Definition: VectorMap.h:120
void erase(iterator __position)
Definition: VectorMap.h:293
vector_type sortedVectorMap
Definition: VectorMap.h:170
iterator begin()
Definition: VectorMap.h:183
const mapped_type & operator[](const key_type &__k) const
Definition: VectorMap.h:224
size_t size() const
Definition: VectorMap.h:201
const mapped_type & at(const key_type &__k) const
Definition: VectorMap.h:242
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:400
bool empty() const
Definition: VectorMap.h:199
bool operator()(const key_type &__x, const value_type &__y) const
Definition: VectorMap.h:159
iterator insert(iterator, const value_type &entry)
Definition: VectorMap.h:279
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:181
const key_type & Key(const size_type &index) const
Definition: VectorMap.h:396
std::reverse_iterator< iterator > reverse_iterator
Definition: VectorMap.h:123
std::pair< iterator, bool > insert(const value_type &entry)
Definition: VectorMap.h:259
const_iterator find(const key_type &key) const
Definition: VectorMap.h:337
iterator find(const key_type &key)
Definition: VectorMap.h:329
iterator lower_bound(const key_type &__x)
Definition: VectorMap.h:349
vector_type::reference reference
Definition: VectorMap.h:118
key_compare key_comp() const
Definition: VectorMap.h:323
mapped_type & operator[](const key_type &key)
Definition: VectorMap.h:205
ptrdiff_t difference_type
Definition: VectorMap.h:125
size_type erase(const key_type &key)
Definition: VectorMap.h:297
value_compare(_Compare __c=_Compare())
Definition: VectorMap.h:144
size_type count(const key_type &__x) const
Definition: VectorMap.h:347
bool operator()(const value_type &__x, const key_type &__y) const
Definition: VectorMap.h:155
void swap(VectorMap &other)
Definition: VectorMap.h:312
friend bool operator==(const VectorMap< _K1, _T1, _C1 > &, const VectorMap< _K1, _T1, _C1 > &)
iterator upper_bound(const key_type &__x)
Definition: VectorMap.h:359
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<.
Definition: VectorMap.h:445
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:354
const_iterator end() const
Definition: VectorMap.h:189
bool operator>=(const VectorMap< _Key, _Tp, _Compare > &__x, const VectorMap< _Key, _Tp, _Compare > &__y)
Based on operator<.
Definition: VectorMap.h:461
bool keyLess(const key_type &__x, const key_type &__y) const
Definition: VectorMap.h:165