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