Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-28 09:20:58

0001 // Copyright (c) 2026 OPEN CASCADE SAS
0002 //
0003 // This file is part of Open CASCADE Technology software library.
0004 //
0005 // This library is free software; you can redistribute it and/or modify it under
0006 // the terms of the GNU Lesser General Public License version 2.1 as published
0007 // by the Free Software Foundation, with special exception defined in the file
0008 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0009 // distribution for complete text of the license and disclaimer of any warranty.
0010 //
0011 // Alternatively, this file may be used under the terms of Open CASCADE
0012 // commercial license or contractual agreement.
0013 
0014 #ifndef NCollection_ForwardRange_HeaderFile
0015 #define NCollection_ForwardRange_HeaderFile
0016 
0017 #include <iterator>
0018 #include <type_traits>
0019 #include <utility>
0020 
0021 //! @file NCollection_ForwardRange.hxx
0022 //! @brief STL range-for adapter for OCCT iterators following the More()/Next() pattern.
0023 //!
0024 //! Provides reusable iterator/sentinel types that enable range-based for loops
0025 //! on any OCCT iterator or explorer class with More(), Next(), and a value accessor.
0026 //!
0027 //! The value accessor is detected automatically via SFINAE with priority:
0028 //! Value() > Current() > CurrentId().
0029 //!
0030 //! Two usage modes:
0031 //! 1. In-class integration: add begin()/end() methods using the provided types.
0032 //!    @code
0033 //!      NCollection_ForwardRangeIterator<MyIterator> begin()
0034 //!      {
0035 //!        return NCollection_ForwardRangeIterator<MyIterator>(this);
0036 //!      }
0037 //!      NCollection_ForwardRangeSentinel end() const { return {}; }
0038 //!    @endcode
0039 //! 2. Standalone wrapper for unmodified classes:
0040 //!    @code
0041 //!      for (const TopoDS_Shape& aFace :
0042 //!           NCollection_ForwardRange(TopExp_Explorer(aShape, TopAbs_FACE)))
0043 //!      {
0044 //!        // ...
0045 //!      }
0046 //!    @endcode
0047 
0048 namespace NCollection_ForwardRangeDetail
0049 {
0050 
0051 //! SFINAE: detect .Value() const
0052 template <typename T, typename = void>
0053 struct HasValue : std::false_type
0054 {
0055 };
0056 
0057 template <typename T>
0058 struct HasValue<T, std::void_t<decltype(std::declval<const T&>().Value())>> : std::true_type
0059 {
0060 };
0061 
0062 //! SFINAE: detect .Current() const
0063 template <typename T, typename = void>
0064 struct HasCurrent : std::false_type
0065 {
0066 };
0067 
0068 template <typename T>
0069 struct HasCurrent<T, std::void_t<decltype(std::declval<const T&>().Current())>> : std::true_type
0070 {
0071 };
0072 
0073 //! SFINAE: detect .CurrentId() const
0074 template <typename T, typename = void>
0075 struct HasCurrentId : std::false_type
0076 {
0077 };
0078 
0079 template <typename T>
0080 struct HasCurrentId<T, std::void_t<decltype(std::declval<const T&>().CurrentId())>> : std::true_type
0081 {
0082 };
0083 
0084 //! Accessor dispatch trait: resolves to the correct value accessor and its return type.
0085 //! Uses std::enable_if_t for mutually-exclusive priority selection.
0086 template <typename T, typename = void>
0087 struct AccessorTraits;
0088 
0089 //! Priority 1: has Value()
0090 template <typename T>
0091 struct AccessorTraits<T, std::enable_if_t<HasValue<T>::value>>
0092 {
0093   using ReturnType = decltype(std::declval<const T&>().Value());
0094 
0095   static ReturnType Get(const T& theIter) { return theIter.Value(); }
0096 };
0097 
0098 //! Priority 2: has Current() but not Value()
0099 template <typename T>
0100 struct AccessorTraits<T, std::enable_if_t<!HasValue<T>::value && HasCurrent<T>::value>>
0101 {
0102   using ReturnType = decltype(std::declval<const T&>().Current());
0103 
0104   static ReturnType Get(const T& theIter) { return theIter.Current(); }
0105 };
0106 
0107 //! Priority 3: has CurrentId() but not Value() or Current()
0108 template <typename T>
0109 struct AccessorTraits<
0110   T,
0111   std::enable_if_t<!HasValue<T>::value && !HasCurrent<T>::value && HasCurrentId<T>::value>>
0112 {
0113   using ReturnType = decltype(std::declval<const T&>().CurrentId());
0114 
0115   static ReturnType Get(const T& theIter) { return theIter.CurrentId(); }
0116 };
0117 
0118 //! Proxy for operator-> when the accessor returns a value (not a reference).
0119 template <typename ValueT>
0120 struct ArrowProxy
0121 {
0122   ValueT myValue;
0123 
0124   const ValueT* operator->() const { return &myValue; }
0125 };
0126 
0127 } // namespace NCollection_ForwardRangeDetail
0128 
0129 //! Empty sentinel type used as the end marker for range-for loops.
0130 struct NCollection_ForwardRangeSentinel
0131 {
0132 };
0133 
0134 //! @brief STL input iterator that wraps an OCCT More()/Next() iterator.
0135 //!
0136 //! Holds a non-owning pointer to the host iterator/explorer.
0137 //! The host must outlive this iterator (guaranteed by range-for semantics).
0138 //!
0139 //! @tparam HostType OCCT iterator/explorer with More(), Next(), and a value accessor.
0140 template <typename HostType>
0141 class NCollection_ForwardRangeIterator
0142 {
0143   using Accessor  = NCollection_ForwardRangeDetail::AccessorTraits<HostType>;
0144   using RawReturn = typename Accessor::ReturnType;
0145 
0146 public:
0147   using value_type        = std::remove_cv_t<std::remove_reference_t<RawReturn>>;
0148   using difference_type   = std::ptrdiff_t;
0149   using iterator_category = std::input_iterator_tag;
0150   using reference         = RawReturn;
0151   using pointer           = std::conditional_t<std::is_reference_v<RawReturn>,
0152                                                std::add_pointer_t<std::remove_reference_t<RawReturn>>,
0153                                                NCollection_ForwardRangeDetail::ArrowProxy<value_type>>;
0154 
0155   //! Construct from a pointer to the host iterator.
0156   explicit NCollection_ForwardRangeIterator(HostType* theHost)
0157       : myHost(theHost)
0158   {
0159   }
0160 
0161   //! Dereference: returns the current value from the host.
0162   RawReturn operator*() const { return Accessor::Get(*myHost); }
0163 
0164   //! Arrow operator: returns a pointer or proxy to the current value.
0165   pointer operator->() const
0166   {
0167     if constexpr (std::is_reference_v<RawReturn>)
0168     {
0169       return &Accessor::Get(*myHost);
0170     }
0171     else
0172     {
0173       return NCollection_ForwardRangeDetail::ArrowProxy<value_type>{Accessor::Get(*myHost)};
0174     }
0175   }
0176 
0177   //! Prefix increment: advances the host iterator.
0178   NCollection_ForwardRangeIterator& operator++()
0179   {
0180     myHost->Next();
0181     return *this;
0182   }
0183 
0184   //! Postfix increment: captures the current value, then advances.
0185   //! Returns a proxy holding the old value (safe for non-copyable hosts).
0186   struct PostfixProxy
0187   {
0188     value_type myValue;
0189 
0190     const value_type& operator*() const { return myValue; }
0191   };
0192 
0193   PostfixProxy operator++(int)
0194   {
0195     PostfixProxy aProxy{Accessor::Get(*myHost)};
0196     myHost->Next();
0197     return aProxy;
0198   }
0199 
0200   //! Equality with sentinel: true when the host is exhausted.
0201   friend bool operator==(const NCollection_ForwardRangeIterator& theLhs,
0202                          NCollection_ForwardRangeSentinel)
0203   {
0204     return !theLhs.myHost->More();
0205   }
0206 
0207   friend bool operator!=(const NCollection_ForwardRangeIterator& theLhs,
0208                          NCollection_ForwardRangeSentinel)
0209   {
0210     return theLhs.myHost->More();
0211   }
0212 
0213   friend bool operator==(NCollection_ForwardRangeSentinel,
0214                          const NCollection_ForwardRangeIterator& theRhs)
0215   {
0216     return !theRhs.myHost->More();
0217   }
0218 
0219   friend bool operator!=(NCollection_ForwardRangeSentinel,
0220                          const NCollection_ForwardRangeIterator& theRhs)
0221   {
0222     return theRhs.myHost->More();
0223   }
0224 
0225 private:
0226   HostType* myHost; //!< Non-owning pointer to the host iterator.
0227 };
0228 
0229 //! @brief Standalone range wrapper for OCCT iterators.
0230 //!
0231 //! Owns a copy/move of the host iterator and provides begin()/end()
0232 //! for range-based for loops. Use this when the host class does not
0233 //! have its own begin()/end() methods.
0234 //!
0235 //! @code
0236 //!   for (const TopoDS_Shape& aFace :
0237 //!        NCollection_ForwardRange(TopExp_Explorer(aShape, TopAbs_FACE)))
0238 //!   {
0239 //!     // process aFace
0240 //!   }
0241 //! @endcode
0242 //!
0243 //! @tparam HostType OCCT iterator/explorer with More(), Next(), and a value accessor.
0244 template <typename HostType>
0245 class NCollection_ForwardRange
0246 {
0247 public:
0248   using iterator       = NCollection_ForwardRangeIterator<HostType>;
0249   using const_iterator = iterator;
0250   using sentinel       = NCollection_ForwardRangeSentinel;
0251 
0252   //! Construct from a copyable host (lvalue).
0253   template <typename U = HostType, typename = std::enable_if_t<std::is_copy_constructible_v<U>>>
0254   explicit NCollection_ForwardRange(const HostType& theHost)
0255       : myHost(theHost)
0256   {
0257   }
0258 
0259   //! Construct from an rvalue (moves the host).
0260   explicit NCollection_ForwardRange(HostType&& theHost)
0261       : myHost(std::move(theHost))
0262   {
0263   }
0264 
0265   NCollection_ForwardRange(const NCollection_ForwardRange&)            = delete;
0266   NCollection_ForwardRange& operator=(const NCollection_ForwardRange&) = delete;
0267   NCollection_ForwardRange(NCollection_ForwardRange&&)                 = default;
0268   NCollection_ForwardRange& operator=(NCollection_ForwardRange&&)      = default;
0269 
0270   //! Returns iterator to the current position of the host.
0271   //! Const-qualified: iteration advances the internal cursor (mutable),
0272   //! not the logical state of the range.
0273   [[nodiscard]] iterator begin() const { return iterator(&myHost); }
0274 
0275   //! Returns sentinel marking the end.
0276   [[nodiscard]] sentinel end() const { return sentinel{}; }
0277 
0278   //! Returns const-access iterator (same as begin).
0279   [[nodiscard]] const_iterator cbegin() const { return const_iterator(&myHost); }
0280 
0281   //! Returns sentinel marking the end.
0282   [[nodiscard]] sentinel cend() const { return sentinel{}; }
0283 
0284 private:
0285   mutable HostType myHost; //!< Owned host iterator (mutable: iteration is cursor movement).
0286 };
0287 
0288 //! CTAD deduction guide: deduces HostType from the constructor argument.
0289 template <typename T>
0290 NCollection_ForwardRange(T&&) -> NCollection_ForwardRange<std::remove_reference_t<T>>;
0291 
0292 #endif // NCollection_ForwardRange_HeaderFile