6789f4ab624a8c5d0bb90977d30f88ac9cca3c16
[occt.git] / src / NCollection / NCollection_StlIterator.hxx
1 // Created on: 2014-04-15
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef NCollection_StlIterator_HeaderFile
17 #define NCollection_StlIterator_HeaderFile
18
19 #include <Standard_Assert.hxx>
20 #include <iterator>
21
22 //! Helper class that allows to use NCollection iterators as STL iterators.
23 //! NCollection iterator can be extended to STL iterator of any category by
24 //! adding necessary methods: STL forward iterator requires IsEqual method,
25 //! STL bidirectional iterator requires Previous method, and STL random access
26 //! iterator requires Offset and Differ methods. See NCollection_Vector as
27 //! example of declaring custom STL iterators.
28 template<class Category, class BaseIterator, class ItemType, bool IsConstant>
29 class NCollection_StlIterator :
30   public std::iterator<Category, ItemType, ptrdiff_t,
31                        typename opencascade::std::conditional<IsConstant, const ItemType*, ItemType*>::type,
32                        typename opencascade::std::conditional<IsConstant, const ItemType&, ItemType&>::type>
33 {
34 public:
35
36   //! Default constructor
37   NCollection_StlIterator () {}
38
39   //! Constructor from NCollection iterator
40   NCollection_StlIterator (const BaseIterator& theIterator)
41     : myIterator (theIterator)
42   { }
43
44   //! Cast from non-const variant to const one
45   NCollection_StlIterator (const NCollection_StlIterator<Category, BaseIterator, ItemType, false>& theIterator)
46     : myIterator (theIterator.Iterator())
47   { }
48
49   //! Assignment of non-const iterator to const one
50   NCollection_StlIterator& operator= (const NCollection_StlIterator<Category, BaseIterator, ItemType, false>& theIterator)
51   {
52     myIterator = theIterator.myIterator;
53     return *this;
54   }
55
56   //! Access to NCollection iterator instance
57   const BaseIterator& Iterator () const
58   {
59     return myIterator;
60   }
61
62   //! Access to NCollection iterator instance
63   BaseIterator& ChangeIterator()
64   {
65     return myIterator;
66   }
67
68 protected: //! @name methods related to forward STL iterator
69
70   // Note: Here we use SFINAE (Substitution failure is not an error) to choose
71   // an appropriate method based on template arguments (at instantiation time).
72
73   template<bool Condition>
74   typename opencascade::std::enable_if<!Condition, ItemType&>::type Reference() const
75   {
76     return myIterator.ChangeValue();
77   }
78
79   template<bool Condition>
80   typename opencascade::std::enable_if<Condition, const ItemType&>::type Reference() const
81   {
82     return myIterator.Value();
83   }
84
85 public: //! @name methods related to forward STL iterator
86
87   //! Test for equality
88   bool operator== (const NCollection_StlIterator& theOther) const
89   {
90     return myIterator.More() == theOther.myIterator.More() &&
91            (!myIterator.More() || myIterator.IsEqual (theOther.myIterator));
92   }
93
94   //! Test for inequality
95   bool operator!= (const NCollection_StlIterator& theOther) const
96   {
97     return !(*this == theOther);
98   }
99
100   //! Get reference to current item
101   typename NCollection_StlIterator::reference operator*() const
102   {
103     return Reference<IsConstant>();
104   }
105
106   //! Dereferencing operator
107   typename NCollection_StlIterator::pointer operator->() const
108   {
109     return &Reference<IsConstant>();
110   }
111
112   //! Prefix increment
113   NCollection_StlIterator& operator++()
114   {
115     myIterator.Next();
116     return *this;
117   }
118
119   //! Postfix increment
120   NCollection_StlIterator operator++(int)
121   {
122     const NCollection_StlIterator theOld (*this);
123     ++(*this);
124     return theOld;
125   }
126
127 public: //! @name methods related to bidirectional STL iterator
128   
129   //! Prefix decrement
130   NCollection_StlIterator& operator--()
131   {
132     Standard_STATIC_ASSERT((opencascade::std::is_same<std::bidirectional_iterator_tag,Category>::value ||
133                             opencascade::std::is_same<std::random_access_iterator_tag,Category>::value));
134     myIterator.Previous();
135     return *this;
136   }
137   
138   //! Postfix decrement
139   NCollection_StlIterator operator--(int)
140   {
141     NCollection_StlIterator theOld (*this);
142     --(*this);
143     return theOld;
144   }
145   
146 public: //! @name methods related to random access STL iterator
147
148   //! Move forward
149   NCollection_StlIterator& operator+= (typename NCollection_StlIterator::difference_type theOffset)
150   {
151     Standard_STATIC_ASSERT((opencascade::std::is_same<std::random_access_iterator_tag,Category>::value));
152     myIterator.Offset (theOffset);
153     return *this;
154   }
155
156   //! Addition
157   NCollection_StlIterator operator+ (typename NCollection_StlIterator::difference_type theOffset) const
158   {
159     NCollection_StlIterator aTemp (*this);
160     return aTemp += theOffset;
161   }
162
163   //! Move backward
164   NCollection_StlIterator& operator-= (typename NCollection_StlIterator::difference_type theOffset)
165   {
166     return *this += -theOffset;
167   }
168
169   //! Decrease
170   NCollection_StlIterator operator- (typename NCollection_StlIterator::difference_type theOffset) const
171   {
172     NCollection_StlIterator aTemp (*this);
173     return aTemp += -theOffset;
174   }
175
176   //! Difference
177   typename NCollection_StlIterator::difference_type operator- (const NCollection_StlIterator& theOther) const
178   {
179     Standard_STATIC_ASSERT((opencascade::std::is_same<std::random_access_iterator_tag,Category>::value));
180     return myIterator.Differ (theOther.myIterator);
181   }
182
183   //! Get item at offset from current
184   typename NCollection_StlIterator::reference operator[] (typename NCollection_StlIterator::difference_type theOffset) const
185   {
186     return *(*this + theOffset);
187   }
188   
189   //! Comparison
190   bool operator< (const NCollection_StlIterator& theOther) const
191   {
192     return (*this - theOther) < 0;
193   }
194
195   //! Comparison
196   bool operator> (const NCollection_StlIterator& theOther) const
197   {
198     return theOther < *this;
199   }
200
201   //! Comparison
202   bool operator<= (const NCollection_StlIterator& theOther) const
203   {
204     return !(theOther < *this);
205   }
206
207   //! Comparison
208   bool operator>= (const NCollection_StlIterator& theOther) const
209   {
210     return !(*this < theOther);
211   }
212
213 private:
214   //! NCollection iterator
215   BaseIterator myIterator;
216 };
217
218 #endif // NCollection_StlIterator_HeaderFile