Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-03-13 09:10:06

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
0003 *                                                                                   *
0004 * This software is distributed under the terms of the Apache version 2 licence,     *
0005 * copied verbatim in the file "LICENSE".                                            *
0006 *                                                                                   *
0007 * In applying this licence, CERN does not waive the privileges and immunities       *
0008 * granted to it by virtue of its status as an Intergovernmental Organization        *
0009 * or submit itself to any jurisdiction.                                             *
0010 \***********************************************************************************/
0011 // ============================================================================
0012 #ifndef GAUDIKERNEL_VECTORMAP_H
0013 #define GAUDIKERNEL_VECTORMAP_H 1
0014 // ============================================================================
0015 // Include files
0016 // ============================================================================
0017 // STD & STL
0018 // ============================================================================
0019 #include <algorithm>
0020 #include <functional>
0021 #include <initializer_list>
0022 #include <ostream>
0023 #include <utility>
0024 #include <vector>
0025 // ============================================================================
0026 // GaudiKernel
0027 // ============================================================================
0028 #include "GaudiKernel/MapBase.h"
0029 
0030 // For parsers
0031 #include "GaudiKernel/StatusCode.h"
0032 #include "GaudiKernel/StringKey.h"
0033 // ============================================================================
0034 namespace GaudiUtils {
0035   // ==========================================================================
0036   /** @class VectorMap GaudiKernel/VectorMap.h
0037    *
0038    *  A bit modified version of 'Loki::AssocVector' associative
0039    *  vector from Loki library by Andrei Alexandrescu
0040    *
0041    *  The number of "non-const" operations is reduced,
0042    *  e.g. all non-const iterators are not exported,
0043    *  therefore it is almost impossible e.g. externally
0044    *  re-sort the underlying sorted container.
0045    *
0046    *  ---------------------------
0047    *  The nominal CPU performance:
0048    *  ---------------------------
0049    *    Container insertion: O(N)
0050    *    Container look-up:   O(log(N)) (a'la std::map, but a bit faster)
0051    *
0052    *  It could be used as a "light" and good alternative
0053    *  for std::map associative container, in the case of
0054    *  relatively rare insertion and frequent look-up.
0055    *
0056    *  Due to helper base class Gaudi::Utils::MapBase, this class
0057    *  is "python-friendly", and one can perform all python
0058    *  manipulaitons
0059    *  in intuitive way:
0060    *  @code
0061    *
0062    *    >>> m = ...        ## get the map
0063    *    >>> print m        ## print the map a'la python class dict
0064    *    ...
0065    *    >>> for key in m :  print key, m[key]   ## iteration over the map
0066    *    ...
0067    *    >>> for key,value in m.iteritems() : print key, value
0068    *    ...
0069    *    >>> keys   = m.keys()                     ## get the list of keys
0070    *    >>> values = m.values ()                  ## get the list of values
0071    *    >>  items  = m.items  ()                  ## get the list of items
0072    *
0073    *    >>> if 'one' in m           ## check the presence of the key in map
0074    *
0075    *    >>>  v = m.get(key', None) ## return m[key] for existing key, else None
0076    *
0077    *    >>>  del m[key]      ## erase the key form the map
0078    *
0079    *    >>> value m[key]     ## unchecked access through the key
0080    *    ...
0081    *    >>> m.update( key, value ) ## update/insert key/value pair
0082    *
0083    *   @endcode
0084    *
0085    *   @attention The syntax can be drastically simplified, if one
0086    *              redefines the __setitem__ attribute:
0087    *
0088    *   @code
0089    *
0090    *    >>> type(m).__setitem__ = Gaudi.Utils.MapBase.__setitem__
0091    *
0092    *    >>> m[key] = value  ## much more intuitive semantics for key insertion
0093    *
0094    *   @endcode
0095    *   In a similar way <c>__getitem__</c> and <c>__delitem__</c> methods
0096    *   can be redefind
0097    *
0098    *   To avoid the unnesessary expansion of dictionaries
0099    *   it is highly recommended to exclude from dictionary the following methods:
0100    *     - lower_bound
0101    *     - upper_bound
0102    *     - equal_range
0103    *     - insert
0104    *
0105    *   @see Gaudi::Utils::MapBase
0106    *
0107    *  @author Vanya BELYAEV Ivan.Belyaev@lapp.in2p3.fr
0108    *  @date   2005-07-23
0109    */
0110   template <class KEY, class VALUE, class KEYCOMPARE = std::less<const KEY>,
0111             class ALLOCATOR = std::allocator<std::pair<KEY, VALUE>>>
0112   class VectorMap : public Gaudi::Utils::MapBase {
0113   public:
0114     // ========================================================================
0115     /// the actual type of key
0116     typedef KEY key_type;
0117     /// the actual type of value
0118     typedef VALUE mapped_type;
0119     /// comparison of keys
0120     typedef KEYCOMPARE key_compare;
0121     /// the actual storage item
0122     typedef std::pair<key_type, mapped_type> value_type;
0123     // ========================================================================
0124   public:
0125     // ========================================================================
0126     /// allocator (could be useful for optimizations)
0127     typedef ALLOCATOR allocator_type;
0128     /// the types to conform STL
0129     typedef typename ALLOCATOR::value_type const& reference;
0130     /// the types to conform STL
0131     typedef typename ALLOCATOR::value_type const& const_reference;
0132     /// the types to conform STL
0133     typedef typename ALLOCATOR::size_type size_type;
0134     /// the types to conform STL
0135     typedef typename ALLOCATOR::difference_type difference_type;
0136     // ========================================================================
0137   public:
0138     // ========================================================================
0139     /// the actual storage container (no export)
0140     typedef std::vector<value_type, allocator_type> _vector;
0141     // ========================================================================
0142   protected:
0143     // ========================================================================
0144     /// the regular iterator  (no export)
0145     typedef typename _vector::iterator _iterator;
0146     // ========================================================================
0147   public:
0148     // ========================================================================
0149     /// visible const_iterator (exported)
0150     typedef typename _vector::const_iterator iterator;
0151     /// visible const_iterator (exported)
0152     typedef typename _vector::const_iterator const_iterator;
0153     /// visible reverse const_iterator (exported)
0154     typedef std::reverse_iterator<iterator> reverse_iterator;
0155     /// visible reverse const_iterator (exported)
0156     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
0157     /// visible iterator pait
0158     typedef std::pair<iterator, iterator> iterators;
0159     /// visible iterator pait
0160     typedef std::pair<iterator, bool> result_type;
0161     // ========================================================================
0162   public:
0163     // ========================================================================
0164     /** @struct _compare_type
0165      *  The actual structure used to compare the elements
0166      *  Only "key" is important for comparison
0167      */
0168     struct _compare_type : public key_compare {
0169     public:
0170       // ======================================================================
0171       /// constructor from the key-comparison criteria
0172       _compare_type( const key_compare& cmp ) : key_compare( cmp ) {}
0173       /// default constructor
0174       _compare_type() : key_compare() {}
0175       /// compare keys: use key_compare
0176       bool operator()( const key_type& k1, const key_type& k2 ) const {
0177         return this->key_compare::operator()( k1, k2 );
0178       }
0179       /// compare pairs (key,mapped): use compare by keys
0180       bool operator()( const value_type& v1, const value_type& v2 ) const { return operator()( v1.first, v2.first ); }
0181       /// compare key and pair (key,mapped): use compare by keys
0182       bool operator()( const key_type& k, const value_type& v ) const { return operator()( k, v.first ); }
0183       /// compare pair (key,mapped) and the key: use compare by keys
0184       bool operator()( const value_type& v, const key_type& k ) const { return operator()( v.first, k ); }
0185       // ======================================================================
0186     };
0187     // ========================================================================
0188     /// the actual comparison criteria for valye_type objects
0189     typedef _compare_type compare_type;
0190     // ========================================================================
0191   public:
0192     // ========================================================================
0193     // sequential access  (only const-versions!)
0194     // ========================================================================
0195     /// "begin"  iterator for sequential access (const-only version!)
0196     iterator begin() const { return m_vct.begin(); }
0197     /// "end"    iterator for sequential access (const-only version!)
0198     iterator end() const { return m_vct.end(); }
0199     /// "rbegin" iterator for sequential access (const-only version!)
0200     reverse_iterator rbegin() const { return m_vct.rbegin(); }
0201     /// "rend"   iterator for sequential access (const-only version!)
0202     reverse_iterator rend() const { return m_vct.rend(); }
0203     // ========================================================================
0204     // list operations : erase & insert
0205     // ========================================================================
0206     /** erase the element using the iterator
0207      *  @param pos position of the element to be erased
0208      */
0209     void erase( iterator pos ) { m_vct.erase( iter( pos ) ); }
0210     // ========================================================================
0211     /** erase the element using the key
0212      *
0213      *  @code
0214      *
0215      *  GaudiUtils::VectorMap<K,V> m = ... ;
0216      *
0217      *  ...
0218      *  K key = ... ;
0219      *
0220      *  std::cout << " # of erased elements "
0221      *            << m.erase ( key ) << std::endl ;
0222      *  @endcode
0223      *
0224      *  @param key key for the element to be erased
0225      *  @return number of erased elements (0 or 1)
0226      */
0227     size_type erase( const key_type& key ) {
0228       iterator pos = find( key );
0229       if ( end() == pos ) { return 0; }
0230       erase( pos );
0231       return 1;
0232     }
0233     // ========================================================================
0234     /** erase the sequence of elements using the iterators
0235      *  @param first begin iterator of sub-sequence to be erased
0236      *  @param end   end iterator of the sub_sequence to be erased
0237      *  @return number of erased elements
0238      */
0239     size_type erase( iterator first, iterator last ) {
0240       m_vct.erase( iter( first ), iter( last ) );
0241       return last - first;
0242     }
0243     // ========================================================================
0244     /** erase the sequence of elements using the sequence of keys
0245      *
0246      *  @code
0247      *
0248      *  GaudiUtils::VectorMap<K,V> m = ... ;
0249      *
0250      *  // some sequence of keys, to be removed
0251      *  KEYS keys = ... ;
0252      *
0253      *  std::cout
0254      *   << " # keys to be removed: " << keys.size()
0255      *   << " # keys removed: " << m.erase( keys.begin() , keys.end() )
0256      *   << std::endl ;
0257      *
0258      *  @endcode
0259      *
0260      *  @param first begin-iterator for the sequence of keys
0261      *  @param last    end-iterator for the sequence of keys
0262      *  @return number of erased elements
0263      */
0264     template <class TYPE>
0265     size_type erase( TYPE first, TYPE last ) {
0266       size_type res = 0;
0267       for ( ; first != last; ++first ) { res += erase( *first ); }
0268       return res;
0269     }
0270     // ========================================================================
0271     /** insert the (key,value) pair into the container
0272      *
0273      *  @attention there is no replacement for the existing key!
0274      *
0275      *  It is STL-compliant behavior for associative containers.
0276      *
0277      *  @code
0278      *
0279      *  GaudiUtils::VectorMap<K,V> m ;
0280      *
0281      *  K key  = ... ;
0282      *  V val1 = ... ;
0283      *  V val2 = ... ;
0284      *
0285      *  std::cout
0286      *     << " Before insert: " << m[key]                  // should be: V()
0287      *     << std::end ;
0288      *
0289      *  // insert the value into the map:
0290      *  const bool inserted1 = m.insert( key , val1 ).second ;
0291      *  std::cout
0292      *     << " 1st insert: "
0293      *     << Gaudi::Utils::toString( inserted1 )           // should be: "True"
0294      *     << " value: " << m[key]                          // should be: val1
0295      *     << std::endl ;
0296      *
0297      *  // try to re-insert another value with the same key:
0298      *  const bool inserted2 = m.insert( key , val2 ).second ;
0299      *  std::cout
0300      *     << " 2nd insert: "
0301      *     << Gaudi::Utils::toString( inserted2 )           // should be: "False"
0302      *     << " value: " << m[key]                          // should be: val1
0303      *     << std::endl ;
0304      *
0305      *  @endcode
0306      *
0307      *  @param  key    key value to be inserted
0308      *  @param  mapped value to be associated with the key
0309      *  @return position of the inserted elements with the flag
0310      *          which allows to distinguish the actual insertion
0311      */
0312     result_type insert( const key_type& key, const mapped_type& mapped ) { return insert( value_type( key, mapped ) ); }
0313     // ========================================================================
0314     /** insert the (key,value) pair into the container
0315      *
0316      *  @attention there is no replacement for the existing element!
0317      *
0318      *  It is STL-compliant behavior for associative containers.
0319      *
0320      *  @code
0321      *
0322      *  GaudiUtils::VectorMap<K,V> m ;
0323      *
0324      *  K key  = ... ;
0325      *  V val1 = ... ;
0326      *  V val2 = ... ;
0327      *
0328      *  std::cout
0329      *     << " Before insert: " << m[key]                  // should be: V()
0330      *     << std::end ;
0331      *
0332      *  // insert the value into the map:
0333      *  const bool inserted1 = m.insert ( std::make_pair( key , val1 ) ).second ;
0334      *  std::cout
0335      *     << " 1st insert: "
0336      *     << Gaudi::Utils::toString( inserted1 )           // should be: "True"
0337      *     << " value: " << m[key]                          // should be: val1
0338      *     << std::endl ;
0339      *
0340      *  // try to re-insert another value with the same key:
0341      *  const bool inserted2 = m.insert ( std::make_pair( key , val2 ) ).second ;
0342      *  std::cout
0343      *     << " 2nd insert: "
0344      *     << Gaudi::Utils::toString( inserted2 )           // should be: "False"
0345      *     << " value: " << m[key]                          // should be: val1
0346      *     << std::endl ;
0347      *
0348      *  @endcode
0349      *
0350      *  @param  value value to be inserted
0351      *  @return position of the inserted elements with the flag
0352      *          which allows to distinguish the actual insertion
0353      */
0354     result_type insert( const value_type& value ) {
0355       bool      found  = true;
0356       _iterator result = lower_bound( value.first );
0357       if ( end() == result || compare( value.first, result->first ) ) {
0358         result = m_vct.insert( result, value );
0359         found  = false;
0360       }
0361       return result_type( iter( result ), !found );
0362     }
0363     // ========================================================================
0364     /** insert the element with some guess about its new position
0365      *  With the right guess the method could be  more efficient
0366      *  @attention there is no replacement for the existing element!
0367      *  @param  pos the guess about position where to insert the element
0368      *  @param  value value to be inserted
0369      *  @return position of the inserted elements with the flag
0370      *          which indicated the actual insertion
0371      */
0372     result_type insert( iterator pos, const value_type& value ) {
0373       if ( pos != end() && compare( *pos, value ) &&
0374            ( pos == end() - 1 || ( !compare( value, *( pos + 1 ) ) && compare( *( pos + 1 ), value ) ) ) ) {
0375         return result_type( m_vct.insert( iter( pos ), value ), true );
0376       }
0377       return insert( value );
0378     }
0379     // ========================================================================
0380     /** insert the (key,value) pair into the container
0381      *  With the right guess the method could be more efficient
0382      *  @attention there is no replacement for the existing element!
0383      *  @param  pos    the guess about position where to insert the element
0384      *  @param  key    key value to be inserted
0385      *  @param  mapped value to be associated with the key
0386      *  @return position of the inserted elements with the flag
0387      *          which indicated the actual insertion
0388      */
0389     result_type insert( iterator pos, const key_type& key, const mapped_type& mapped ) {
0390       return insert( pos, value_type( key, mapped ) );
0391     }
0392     // ========================================================================
0393     /** insert the sequence of elements into the container
0394      *  @attention there is no replacement for the existing element!
0395      *  @param first the begin iterator of the sequence
0396      *  @param last the end iterator of the sequence
0397      */
0398     template <class PAIRS>
0399     void insert( PAIRS first, PAIRS last ) {
0400       for ( ; first != last; ++first ) { insert( *first ); }
0401     }
0402     // ========================================================================
0403     /** insert into the container the elements from
0404      *  2 "parallel" sequences
0405      *  @attention there is no replacement for the existing element!
0406      *  @param kf the begin iterator of the sequence of keys
0407      *  @param kl the end iterator of the sequence of keys
0408      *  @param vf the begin iterator of the sequence of values
0409      */
0410     template <class KEYS, class VALUES>
0411     void insert( KEYS kf, KEYS kl, VALUES vf ) {
0412       for ( ; kf != kl; ++kf, ++vf ) { insert( *kf, *vf ); }
0413     }
0414     // ========================================================================
0415     // map operations: lookup, count, ...
0416     // ========================================================================
0417     /** find the element by key
0418      *
0419      *  @code
0420      *
0421      *  typedef GaudiUtils::VectorMap<K,V> Map ;
0422      *
0423      *  Map m  = ... ;
0424      *
0425      *  K key = ...;
0426      *
0427      *  // Is key in the container?
0428      *  Map::iterator ifound = m.find( key ) ;
0429      *
0430      *  if ( m.end() != ifound )
0431      *   {
0432      *     std::cout << "The value is : " << ifound->second << std::endl ;
0433      *   }
0434      *
0435      *  @endcode
0436      *
0437      *  @param key key to be searched
0438      *  @return iterator to the element position in the container
0439      */
0440     iterator find( const key_type& key ) const {
0441       iterator res = lower_bound( key );
0442       if ( end() != res && compare( key, res->first ) ) { res = end(); }
0443       return res;
0444     }
0445     // ========================================================================
0446     /** count number of elements with the certain key
0447      *
0448      *  @code
0449      *
0450      *  GaudiUtils::VectorMap<K,V> m = ... ;
0451      *
0452      *  K key = ... ;
0453      *
0454      *  std::cout << " # of elements for the key: " << m.count(key) << std::end ;
0455      *
0456      *  @endcode
0457      *
0458      *  @param key key to be searched
0459      *  @return number of elements with the given key (0 or 1)
0460      */
0461     size_type count( const key_type& key ) const { return end() == find( key ) ? 0 : 1; }
0462     // ========================================================================
0463     iterator  lower_bound( const key_type& key ) const { return std::lower_bound( begin(), end(), key, compare() ); }
0464     iterator  upper_bound( const key_type& key ) const { return std::upper_bound( begin(), end(), key, compare() ); }
0465     iterators equal_range( const key_type& key ) const { return std::equal_range( begin(), end(), key, compare() ); }
0466     // ========================================================================
0467     // general container operations :
0468     // ========================================================================
0469     /// empty container ?
0470     bool empty() const { return m_vct.empty(); }
0471     /// number of elements
0472     size_type size() const { return m_vct.size(); }
0473     /// maximal allowed size
0474     size_type max_size() const { return m_vct.max_size(); }
0475     /// clear the container
0476     void clear() { m_vct.clear(); }
0477     /// reserve the space in the container for at least 'num' elements
0478     void reserve( size_type num ) { m_vct.reserve( num ); }
0479     // ========================================================================
0480     /// swap function, which 'swaps' the content of two containers
0481     void swap( VectorMap& other ) { std::swap( m_vct, other.m_vct ); }
0482     // ========================================================================
0483     // The basic comparison operators for container
0484     // ========================================================================
0485     /// comparison criteria for containers
0486     bool operator==( const VectorMap& other ) const { return m_vct == other.m_vct; }
0487     /// comparison criteria for containers
0488     bool operator<( const VectorMap& other ) const { return m_vct < other.m_vct; }
0489     // ========================================================================
0490     // The derived comparison operators for container
0491     // ========================================================================
0492     friend bool operator>( const VectorMap& left, const VectorMap& right ) { return right < left; }
0493     friend bool operator!=( const VectorMap& left, const VectorMap& right ) { return !( left == right ); }
0494     friend bool operator>=( const VectorMap& left, const VectorMap& right ) { return !( left < right ); }
0495     friend bool operator<=( const VectorMap& left, const VectorMap& right ) { return !( right < left ); }
0496     // ========================================================================
0497     /** forced insertion of the key/mapped pair
0498      *  The method acts like "insert" but it *DOES*
0499      *  overwrite the existing mapped value.
0500      *
0501      *  @attention There is no STL analogue
0502      *
0503      *  The method is added on request from ATLAS
0504      *  (see Savannah report #21395 and #21394)
0505      *
0506      *  @code
0507      *
0508      *  GaudiUtils::VectorMap<K,V> m = ... ;
0509      *
0510      *  K key  = ... ;
0511      *  V val1 = ... ;
0512      *  V val2 = ... ;
0513      *
0514      *  std::cout << "Value " << m[key] << std::endl ; // should be: V()
0515      *  m.update ( key , val1 ) ;
0516      *  std::cout << "Value " << m[key] << std::endl ; // should be: val1
0517      *  m.update ( key , val2 ) ;
0518      *  std::cout << "Value " << m[key] << std::endl ; // should be: val2
0519      *
0520      *  @endcode
0521      *
0522      *  @param key key value
0523      *  @param mapped mapped value
0524      *  @return true if the existing value has been replaced
0525      */
0526     bool update( const key_type& key, const mapped_type& mapped ) {
0527       _iterator result = lower_bound( key );
0528       if ( end() == result || compare( key, result->first ) ) {
0529         result = m_vct.insert( result, value_type( key, mapped ) );
0530         return false;
0531       } else {
0532         result->second = mapped;
0533       }
0534       //
0535       return true;
0536     }
0537     // ========================================================================
0538     /** forced insertion of the key/mapped pair
0539      *  The method acts like "insert" but it *DOES*
0540      *  overwrite the mapped value.
0541      *
0542      *  @attention There is no STL analogue
0543      *
0544      *  The method is added on request from ATLAS
0545      *  (see Savannah report #21395 and #21394)
0546      *
0547      *  @code
0548      *
0549      *  GaudiUtils::VectorMap<K,V> m = ... ;
0550      *
0551      *  K key  = ... ;
0552      *  V val1 = ... ;
0553      *  V val2 = ... ;
0554      *
0555      *  std::cout << "Value " << m[key] << std::endl ; // should be: V()
0556      *  m.update ( std::make_pair ( key , val1 ) ) ;
0557      *  std::cout << "Value " << m[key] << std::endl ; // should be: val1
0558      *  m.update ( std::make_pair ( key , val2 ) ) ;
0559      *  std::cout << "Value " << m[key] << std::endl ; // should be: val2
0560      *
0561      *  @endcode
0562      *
0563      *  @param  val a pair of (key,value)
0564      *  @return true if the existing value has been replaced
0565      */
0566     bool update( const value_type& val ) { return update( val.first, val.second ); }
0567     // ========================================================================
0568     /** access to element by key (const version)
0569      *  there is no container increment for missing keys
0570      *
0571      *  @attention The behavior different from std::map,
0572      *             it is similar to GaudiUtils::Map
0573      *
0574      *  The method is added on request from ATLAS
0575      *  (see Savannah report #21395 and #21394)
0576      *  For typical usage of this class in LHCb context
0577      *  as "ExtraInfo" field I would like to recommend
0578      *  to AVOID this method
0579      *
0580      *  @code
0581      *
0582      *   GaudiUtils::VectorMap<K,V> m = ... ;
0583      *
0584      *   // OK:
0585      *   K key = ... ;
0586      *   std::cout << " Value: " << m(key) << std::end ; // it is OK!
0587      *
0588      *   // ERROR:
0589      *   V value = ... ;
0590      *   m(key) = value ;                                // ERROR!
0591      *
0592      *   @endcode
0593      *
0594      *  @see GaudiUtils::Map
0595      *  @param key key value
0596      *  @return mapped value for existing key and the
0597      *                 default value for non-existing key
0598      */
0599     const mapped_type& operator()( const key_type& key ) const {
0600       static const mapped_type s_default = mapped_type();
0601       iterator                 res       = find( key );
0602       if ( end() == res ) { return s_default; }
0603       return res->second;
0604     }
0605     // ========================================================================
0606     /** access to element by key (const version)
0607      *  there is no container increment for missing keys
0608      *
0609      *  @attention The behavior different from std::map,
0610      *             it is similar to GaudiUtils::Map
0611      *
0612      *  The method is added on request from ATLAS
0613      *  (see Savannah report #21395 and #21394)
0614      *  For typical usage of this class in LHCb context
0615      *  as "ExtraInfo" field I would like to recommend
0616      *  to AVOID this method
0617      *
0618      *  @code
0619      *
0620      *   GaudiUtils::VectorMap<K,V> m = ... ;
0621      *
0622      *   // OK:
0623      *   K key = ... ;
0624      *   std::cout << " Value: " << m[key] << std::end ; // it is OK!
0625      *
0626      *   // ERROR:
0627      *   V value = ... ;
0628      *   m[key] = value ;                                // ERROR!
0629      *
0630      *   @endcode
0631      *
0632      *  @see GaudiUtils::Map
0633      *  @param key key value
0634      *  @return mapped value
0635      */
0636     const mapped_type& operator[]( const key_type& key ) const { return ( *this )( key ); }
0637     // ========================================================================
0638     /** checked access to elements by key
0639      *  throw std::out_of_range exception for non-existing keys
0640      *
0641      *  @code
0642      *
0643      *   GaudiUtils::VectorMap<K,V> m = ... ;
0644      *
0645      *   // OK:
0646      *   K key = ... ;
0647      *   std::cout << " Value: " << m.at(key) << std::end ; // it is OK!
0648      *
0649      *  @endcode
0650      *
0651      *  @exception std::out_of_range for non-existing keys
0652      *  @param key key value
0653      *  @return mapped value
0654      */
0655     const mapped_type& at( const key_type& key ) const {
0656       iterator res = find( key );
0657       if ( end() == res ) { this->throw_out_of_range_exception(); }
0658       return res->second;
0659     }
0660     // ========================================================================
0661   public:
0662     // ========================================================================
0663     // Constructors, destructors, etc.
0664     // ========================================================================
0665     /** default constructor from the the allocator
0666      *  @param cmp comparison criteria for the key
0667      *  @param alloc allocator to be used
0668      */
0669     VectorMap( const allocator_type& alloc = allocator_type() ) : m_vct( alloc ) {}
0670     // ========================================================================
0671     /** templated constructor from "convertible" sequence
0672      *  @param first 'begin'-iterator for the convertible sequence
0673      *  @param last  'end'-iterator for the convertible sequence
0674      *  @param cmp comparison criteria for the key
0675      *  @param alloc allocator to be used
0676      */
0677     template <class INPUT>
0678     VectorMap( INPUT first, INPUT last, const allocator_type& alloc = allocator_type() ) : m_vct( first, last, alloc ) {
0679       std::sort( m_vct.begin(), m_vct.end(), compare() );
0680     }
0681     // ========================================================================
0682     /** tconstructor from initializer list
0683      *  @param list
0684      *  @param cmp comparison criteria for the key
0685      *  @param alloc allocator to be used
0686      */
0687     VectorMap( std::initializer_list<value_type> first, const allocator_type& alloc = allocator_type() )
0688         : m_vct( first, alloc ) {
0689       std::sort( m_vct.begin(), m_vct.end(), compare() );
0690     }
0691     // ========================================================================
0692   public:
0693     // ========================================================================
0694     // The specific public accessors
0695     // ========================================================================
0696     /// get the comparison criteria itself
0697     const compare_type& compare() const {
0698       static const compare_type s_cmp = compare_type();
0699       return s_cmp;
0700     }
0701     /// get the comparison criteria for keys
0702     const key_compare& compare_key() const { return compare(); }
0703     /// printout to ostream - not implemented
0704     friend std::ostream& operator<<( std::ostream& str, const VectorMap& /* obj */ ) { return str; }
0705     // ========================================================================
0706   public:
0707     // ========================================================================
0708     /// merge two maps
0709     inline VectorMap& merge( const VectorMap& right ) {
0710       for ( const auto& i : right ) { update( i.first, i.second ); }
0711       return *this;
0712     }
0713     /// merge two maps
0714     template <class K1, class K2, class K3, class K4>
0715     inline VectorMap& merge( const VectorMap<K1, K2, K3, K4>& right ) {
0716       for ( const auto& i : right ) { update( i.first, i.second ); }
0717       return *this;
0718     }
0719     // ========================================================================
0720   public:
0721     // ========================================================================
0722     /** useful method for python decoration:
0723      *  @param index (INPUT) the index
0724      *  @return the key at given index
0725      *  @exception std::out_of_range for invalid index
0726      */
0727     const key_type& key_at( const size_t index ) const {
0728       if ( index >= size() ) { this->throw_out_of_range_exception(); }
0729       auto it = this->begin();
0730       std::advance( it, index );
0731       return it->first;
0732     }
0733     /** useful method for python decoration:
0734      *  @param index (INPUT) the index
0735      *  @return the value at given index
0736      *  @exception std::out_of_range for invalid index
0737      */
0738     const mapped_type& value_at( const size_t index ) const {
0739       if ( index >= size() ) { this->throw_out_of_range_exception(); }
0740       auto it = this->begin();
0741       std::advance( it, index );
0742       return it->second;
0743     }
0744     // ========================================================================
0745   protected:
0746     // ========================================================================
0747     // Pure technical helper functions
0748     // ========================================================================
0749     /** compare the objects using the comaprison criteria
0750      *  @param obj the first object
0751      *  @param obj the second object
0752      *  @return result of (obj1,obj2) comparison
0753      */
0754     template <class TYPE1, class TYPE2>
0755     bool compare( const TYPE1& obj1, const TYPE2& obj2 ) const {
0756       return compare()( obj1, obj2 );
0757     }
0758     // ========================================================================
0759     /// 'lower-bound' - non-const version
0760     _iterator lower_bound( const key_type& key ) {
0761       return std::lower_bound( m_vct.begin(), m_vct.end(), key, compare() );
0762     }
0763     // ========================================================================
0764     /// the conversion from 'const' to 'non-const' iterator
0765     _iterator iter( iterator p ) {
0766       auto result = m_vct.begin();
0767       std::advance( result, std::distance( begin(), p ) );
0768       return result;
0769     }
0770     // ========================================================================
0771     /// the conversion from 'non-const' to 'const' iterator
0772     iterator iter( _iterator p ) {
0773       auto result = begin();
0774       std::advance( result, std::distance( m_vct.begin(), p ) );
0775       return result;
0776     }
0777     // ========================================================================
0778   private:
0779     // ========================================================================
0780     /// the underlying sorted vector of (key,mapped) pairs
0781     _vector m_vct; // the underlying sorted vector of (key,mapped) pairs
0782     // ========================================================================
0783   };
0784   // ==========================================================================
0785 } //                                               end of namespace GaudiUtils
0786 // ============================================================================
0787 namespace std {
0788   // ==========================================================================
0789   /** the definition of specialized algorithm for swapping
0790    *  @param left  object to be swapped
0791    *  @param right object to be swapped
0792    */
0793   template <class KEY, class VALUE, class KEYCOMPARE, class ALLOCATOR>
0794   inline void swap( GaudiUtils::VectorMap<KEY, VALUE, KEYCOMPARE, ALLOCATOR>& left,
0795                     GaudiUtils::VectorMap<KEY, VALUE, KEYCOMPARE, ALLOCATOR>& right ) {
0796     left.swap( right );
0797   }
0798   // ===========================================================================
0799 } //                                                       end of namespace std
0800 // ============================================================================
0801 // ============================================================================
0802 namespace Gaudi {
0803   // ==========================================================================
0804   namespace Parsers {
0805     // ========================================================================
0806     /** parse the key from the string
0807      *  @see Gaudi::Parsers
0808      *  @see Gaudi::Parsers::parse
0809      *  @see Gaudi::VectorMap
0810      *  @attention: this function is needed to use it as property
0811      *  @param result (OUTPUT) the parsing result
0812      *  @param input the input string
0813      *  @return status code
0814      */
0815     GAUDI_API StatusCode parse( GaudiUtils::VectorMap<std::string, double>& result, const std::string& input );
0816     // ========================================================================
0817     /** parse the vector of keys from the string
0818      *  @see Gaudi::Parsers
0819      *  @see Gaudi::Parsers::parse
0820      *  @see Gaudi::VectorMap
0821      *  @see Gaudi::StringKey
0822      *  @attention: this function is needed to use it as property
0823      *  @param result (OUTPUT) the parsing result
0824      *  @param input the input string
0825      *  @return status code
0826      */
0827     GAUDI_API StatusCode parse( GaudiUtils::VectorMap<Gaudi::StringKey, double>& result, const std::string& input );
0828     // ========================================================================
0829   } // namespace Parsers
0830   // ==========================================================================
0831 } //                                                     end of namespace Gaudi
0832 
0833 // ============================================================================
0834 // The END
0835 // ============================================================================
0836 #endif // GAUDIKERNEL_MAPS_H