|
||||
File indexing completed on 2025-01-30 10:07:18
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 #ifndef GAUDI_RANGE_H 0012 #define GAUDI_RANGE_H 1 0013 // ============================================================================ 0014 // Include files 0015 // ============================================================================ 0016 // STD & STL 0017 // ============================================================================ 0018 #include <algorithm> 0019 #include <utility> 0020 #include <vector> 0021 // ============================================================================ 0022 // GaudiKernel 0023 // ============================================================================ 0024 #include "GaudiKernel/Kernel.h" 0025 #include "GaudiKernel/detected.h" 0026 // ============================================================================ 0027 /** @file 0028 * 0029 * This file has been imported from 0030 * <a href="http://savannah.cern.ch/projects/loki">LoKi project</a> 0031 * <a href="http://cern.ch/lhcb%2Dcomp/Analysis/Loki"> 0032 * "C++ ToolKit for Smart and Friendly Physics Analysis"</a> 0033 * 0034 * The package has been designed with the kind help from 0035 * Galina PAKHLOVA and Sergey BARSUK. Many bright ideas, 0036 * contributions and advises from G.Raven, J.van Tilburg, 0037 * A.Golutvin, P.Koppenburg have been used in the design. 0038 * 0039 * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl 0040 * @date 2001-01-23 0041 */ 0042 // ============================================================================ 0043 namespace Gaudi { 0044 // ========================================================================== 0045 namespace details { 0046 // ======================================================================== 0047 /** Helpful function to throw an "out-of-range exception" for class Range_ 0048 * @see GaudiException 0049 * @param index invalid index 0050 * @param size range size 0051 */ 0052 GAUDI_API void rangeException( const long index, const size_t size ); 0053 // ======================================================================== 0054 /// helper structure to get container type 0055 template <class CONTAINER> 0056 struct container { 0057 template <typename T> 0058 using _has_container_t = typename T::Container; 0059 using Container = Gaudi::cpp17::detected_or_t<CONTAINER, _has_container_t, CONTAINER>; 0060 using Iterator = typename CONTAINER::const_iterator; 0061 }; 0062 // ========================================================================= 0063 } // namespace details 0064 // ========================================================================== 0065 /** @struct RangeBase_ GaudiUtils/Range.h 0066 * helper class to simplify the dealing with ranges in Python 0067 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 0068 * @date 2006-09-01 0069 */ 0070 struct RangeBase_ {}; 0071 // ========================================================================== 0072 /** @class Range_ Range.h GaudiUtils/Range.h 0073 * 0074 * Useful class for representation of "sequence" of the objects 0075 * through the range of valid iterators. 0076 * 0077 * The range could be created over *ALL* container types which 0078 * supports at least bidirectional iterators. 0079 * 0080 * The minimum requirements from the container type: 0081 * - support the concept of "CONTAINER::value_type" 0082 * - support the concept of "CONTAINER::const_iterator" 0083 * - support the concept of "CONTAINER::const_reference" 0084 * - support the concept of "CONTAINER::const_reverse_iterator" 0085 * - the iterator should be ok for "std::distance" and "std::advance" 0086 * - support for "const_iterator CONTAINER::begin () const" 0087 * - support for "const_iterator CONTAINER::end () const" 0088 * - support for "const_reverse_iterator CONTAINER::rbegin () const" 0089 * - support for "const_reverse_iterator CONTAINER::rend () const" 0090 * 0091 * @author Vanya Belyaev Ivan.Belyaev@itep.ru 0092 * @date 2002-07-12 0093 */ 0094 template <class CONTAINER, class ITERATOR = typename Gaudi::details::container<CONTAINER>::Iterator> 0095 class Range_ : public RangeBase_ { 0096 public: 0097 // ======================================================================== 0098 typedef std::pair<ITERATOR, ITERATOR> Base; 0099 // ======================================================================== 0100 public: 0101 // ======================================================================== 0102 /// type for actual contained iterator 0103 typedef typename Gaudi::details::container<CONTAINER>::Container Container; 0104 // 0105 typedef ITERATOR iterator; 0106 typedef ITERATOR const_iterator; 0107 // 0108 private: 0109 // 0110 typedef typename std::iterator_traits<iterator> iter_traits; 0111 // 0112 public: 0113 // 0114 typedef typename iter_traits::value_type value_type; 0115 typedef typename iter_traits::reference reference; 0116 typedef typename iter_traits::reference const_reference; 0117 // 0118 typedef std::reverse_iterator<iterator> reverse_iterator; 0119 typedef std::reverse_iterator<iterator> const_reverse_iterator; 0120 /// internal types 0121 // ======================================================================== 0122 public: 0123 // ======================================================================== 0124 /// default constructor 0125 Range_() = default; 0126 /** Constructor 0127 * @param ibegin iterator to begin of the sequence 0128 * @param iend iterator to end of the sequence 0129 */ 0130 template <typename InputIterator> 0131 Range_( InputIterator first, InputIterator last ) : m_base( first, last ) {} 0132 /** constructor from the pair of iterators 0133 * @param base pair of the iterators 0134 */ 0135 Range_( const Base& base ) : m_base( base ) {} 0136 /** constructor from the container 0137 * @param cont reference to the container 0138 */ 0139 Range_( const Container& cont ) : m_base( cont.begin(), cont.end() ) {} 0140 /* constructor of empty range/sequence 0141 * @param ibegin iterator to begin of empty sequence 0142 */ 0143 Range_( iterator ibegin ) : m_base( ibegin, ibegin ) {} 0144 /// destructor 0145 ~Range_() = default; 0146 // ======================================================================== 0147 /// empty sequence ? 0148 bool empty() const { return m_base.second == m_base.first; } 0149 /// size of the sequence (number of elements) 0150 size_t size() const { return std::distance( m_base.first, m_base.second ); } 0151 /// access to begin of the sequence (const version ) 0152 iterator begin() const { return m_base.first; } 0153 /// access to end of the sequence (const version) 0154 iterator end() const { return m_base.second; } 0155 /// access to begin of the sequence (const version ) 0156 iterator cbegin() const { return m_base.first; } 0157 /// access to end of the sequence (const version) 0158 iterator cend() const { return m_base.second; } 0159 /// access to begin of the reversed sequence (const) 0160 reverse_iterator rbegin() const { return reverse_iterator( end() ); } 0161 /// access to begin of the reversed sequence (const) 0162 reverse_iterator rend() const { return reverse_iterator( begin() ); } 0163 /// access for the first element (only for non-empty ranges!) 0164 const_reference front() const { return *begin(); } 0165 /// access for the back element (only for non-empty ranges!) 0166 const_reference back() const { return *std::prev( end() ); } 0167 // ======================================================================== 0168 /// get a "slice" of a range, in Python style 0169 Range_ slice( long index1, long index2 ) const { 0170 // trivial cases 0171 if ( empty() || index1 == index2 ) { return Range_(); } // RETURN 0172 // adjust indices 0173 if ( index1 < 0 ) { index1 += size(); } 0174 if ( index2 < 0 ) { index2 += size(); } 0175 // check 0176 if ( index1 < 0 ) { return Range_(); } // RETURN 0177 if ( index2 < index1 ) { return Range_(); } // RETURN 0178 0179 if ( index1 > (long)size() ) { return Range_(); } // RETURN 0180 if ( index2 > (long)size() ) { index2 = size(); } 0181 0182 // construct the slice 0183 return Range_( std::next( begin(), index1 ), std::next( begin(), index2 ) ); // RETURN 0184 } 0185 // ======================================================================== 0186 /** non-checked access to the elements by index 0187 * (valid only for non-empty sequences) 0188 * @param index the index of the lement to be accessed 0189 */ 0190 inline const_reference operator()( const size_t index ) const { return *std::next( begin(), index ); } 0191 /** non-checked access to the elements by index 0192 * (valid only for non-empty sequences) 0193 * @param index the index of the lement to be accessed 0194 */ 0195 inline const_reference operator[]( const long index ) const { return ( *this )( index ); } 0196 /** Checked access to the elements by index 0197 * (valid for all sequences) 0198 * @exception GaudiException for out-of-range access 0199 * @param index the index of the element to be accessed 0200 */ 0201 inline const_reference at( const long index ) const { 0202 if ( index < 0 || index >= (long)size() ) { Gaudi::details::rangeException( index, size() ); } 0203 return ( *this )( index ); 0204 } 0205 // ======================================================================== 0206 public: 0207 // ======================================================================== 0208 /// compare with another range 0209 template <class C, class I> 0210 bool operator<( const Range_<C, I>& right ) const { 0211 return std::lexicographical_compare( begin(), end(), right.begin(), right.end() ); 0212 } 0213 /// compare with another container 0214 template <class ANOTHERCONTAINER> 0215 bool operator<( const ANOTHERCONTAINER& right ) const { 0216 return std::lexicographical_compare( begin(), end(), right.begin(), right.end() ); 0217 } 0218 // ======================================================================== 0219 public: 0220 // ======================================================================== 0221 /// equality with another range 0222 bool operator==( const Range_& right ) const { 0223 if ( &right == this ) { return true; } // RETURN 0224 return right.size() == size() && std::equal( begin(), end(), right.begin() ); 0225 } 0226 /// compare with another container 0227 template <class ANOTHERCONTAINER> 0228 bool operator==( const ANOTHERCONTAINER& right ) const { 0229 return right.size() == size() && std::equal( begin(), end(), right.begin() ); 0230 } 0231 // ======================================================================== 0232 public: 0233 // ======================================================================== 0234 /// empty sequence? 0235 bool operator!() const { return empty(); } 0236 /// non-empty sequence? 0237 explicit operator bool() const { return !empty(); } 0238 // ======================================================================== 0239 public: 0240 // ======================================================================== 0241 /// conversion operator to the std::pair 0242 operator const Base&() const { return base(); } 0243 /// conversion operator to the std::pair 0244 inline const Base& base() const { return m_base; } 0245 // ======================================================================== 0246 private: 0247 // ======================================================================== 0248 // the base itself 0249 Base m_base; ///< the base itself 0250 // ======================================================================== 0251 }; // end of class Range_ 0252 // ========================================================================== 0253 /** simple function to create the range from the arbitrary container 0254 * 0255 * @code 0256 * 0257 * const CONTAINER& cnt = ... ; 0258 * 0259 * Range_<CONTAINER> r = range ( cnt ) ; 0260 * 0261 * @endcode 0262 * 0263 * The range could be created over *ALL* container types which 0264 * supports at least the bidirectional iterators. 0265 * 0266 * The minimum requirements from the container type: 0267 * - support the concept of "CONTAINER::value_type" 0268 * - support the concept of "CONTAINER::const_iterator" 0269 * - support the concept of "CONTAINER::const_reference" 0270 * - support the concept of "CONTAINER::const_reverse_iterator" 0271 * - the iterator should be ok for "std::distance" and "std::advance" 0272 * - support for "const_iterator CONTAINER::begin () const" 0273 * - support for "const_iterator CONTAINER::end () const" 0274 * - support for "const_reverse_iterator CONTAINER::rbegin () const" 0275 * - support for "const_reverse_iterator CONTAINER::rend () const" 0276 * 0277 * @author Vanya BELYAEV ibelyaev@physics.syre.edu 0278 * @date 2007-11-29 0279 */ 0280 template <class CONTAINER> 0281 inline Range_<CONTAINER> range( const CONTAINER& cnt ) { 0282 return Range_<CONTAINER>( cnt.begin(), cnt.end() ); 0283 } 0284 // ========================================================================== 0285 } // end of namespace Gaudi 0286 // ============================================================================ 0287 // The END 0288 // ============================================================================ 0289 #endif // GAUDI_RANGE_H
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |