0028186: Foundation Classes, NCollection_List - methods "Remove" and "Contains" preve...
[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 // This file uses C++11 utilities like std::is_base<>, which are not 
23 // available in some environments (e.g. MSVC includes them since VS 2008).
24 // Hence here we define our own implementation of these tools in namespace opencascade.
25 // When all compilers support this, this namespace can be removed and replaced by std.
26 namespace opencascade
27 {
28   template<bool Condition, typename T>
29   struct enable_if
30   {
31     typedef T type;
32   };
33   
34   template<typename T>
35   struct enable_if<false, T>
36   {
37   };
38   
39   template<typename T1, typename T2>
40   struct is_same
41   {
42     enum { value = 0 };
43   };
44   
45   template<typename T>
46   struct is_same<T, T>
47   {
48     enum { value = 1 };
49   };
50   
51   template<bool Condition, typename TypeTrue, typename TypeFalse>
52   struct conditional
53   {
54     typedef TypeTrue type;
55   };
56
57   template<typename TypeTrue, typename TypeFalse>
58   struct conditional<false, TypeTrue, TypeFalse>
59   {
60     typedef TypeFalse type;
61   };
62 }
63
64 //! Helper class that allows to use NCollection iterators as STL iterators.
65 //! NCollection iterator can be extended to STL iterator of any category by
66 //! adding necessary methods: STL forward iterator requires IsEqual method,
67 //! STL bidirectional iterator requires Previous method, and STL random access
68 //! iterator requires Offset and Differ methods. See NCollection_Vector as
69 //! example of declaring custom STL iterators.
70 template<class Category, class BaseIterator, class ItemType, bool IsConstant>
71 class NCollection_StlIterator :
72   public std::iterator<Category, ItemType, ptrdiff_t,
73                        typename opencascade::conditional<IsConstant, const ItemType*, ItemType*>::type,
74                        typename opencascade::conditional<IsConstant, const ItemType&, ItemType&>::type>
75 {
76 public:
77
78   //! Default constructor
79   NCollection_StlIterator () {}
80
81   //! Constructor from NCollection iterator
82   NCollection_StlIterator (const BaseIterator& theIterator)
83     : myIterator (theIterator)
84   { }
85
86   //! Cast from non-const variant to const one
87   NCollection_StlIterator (const NCollection_StlIterator<Category, BaseIterator, ItemType, false>& theIterator)
88     : myIterator (theIterator.Iterator())
89   { }
90
91   //! Assignment of non-const iterator to const one
92   NCollection_StlIterator& operator= (const NCollection_StlIterator<Category, BaseIterator, ItemType, false>& theIterator)
93   {
94     myIterator = theIterator.myIterator;
95     return *this;
96   }
97
98   //! Access to NCollection iterator instance
99   const BaseIterator& Iterator () const
100   {
101     return myIterator;
102   }
103
104   //! Access to NCollection iterator instance
105   BaseIterator& ChangeIterator()
106   {
107     return myIterator;
108   }
109
110 protected: //! @name methods related to forward STL iterator
111
112   // Note: Here we use SFINAE (Substitution failure is not an error) to choose
113   // an appropriate method based on template arguments (at instantiation time).
114
115   template<bool Condition>
116   typename opencascade::enable_if<!Condition, ItemType&>::type Reference() const
117   {
118     return myIterator.ChangeValue();
119   }
120
121   template<bool Condition>
122   typename opencascade::enable_if<Condition, const ItemType&>::type Reference() const
123   {
124     return myIterator.Value();
125   }
126
127 public: //! @name methods related to forward STL iterator
128
129   //! Test for equality
130   bool operator== (const NCollection_StlIterator& theOther) const
131   {
132     return myIterator.More() == theOther.myIterator.More() &&
133            (!myIterator.More() || myIterator.IsEqual (theOther.myIterator));
134   }
135
136   //! Test for inequality
137   bool operator!= (const NCollection_StlIterator& theOther) const
138   {
139     return !(*this == theOther);
140   }
141
142   //! Get reference to current item
143   typename NCollection_StlIterator::reference operator*() const
144   {
145     return Reference<IsConstant>();
146   }
147
148   //! Dereferencing operator
149   typename NCollection_StlIterator::pointer operator->() const
150   {
151     return &Reference<IsConstant>();
152   }
153
154   //! Prefix increment
155   NCollection_StlIterator& operator++()
156   {
157     myIterator.Next();
158     return *this;
159   }
160
161   //! Postfix increment
162   NCollection_StlIterator operator++(int)
163   {
164     const NCollection_StlIterator theOld (*this);
165     ++(*this);
166     return theOld;
167   }
168
169 public: //! @name methods related to bidirectional STL iterator
170   
171   //! Prefix decrement
172   NCollection_StlIterator& operator--()
173   {
174     Standard_STATIC_ASSERT((opencascade::is_same<std::bidirectional_iterator_tag,Category>::value ||
175                             opencascade::is_same<std::random_access_iterator_tag,Category>::value));
176     myIterator.Previous();
177     return *this;
178   }
179   
180   //! Postfix decrement
181   NCollection_StlIterator operator--(int)
182   {
183     NCollection_StlIterator theOld (*this);
184     --(*this);
185     return theOld;
186   }
187   
188 public: //! @name methods related to random access STL iterator
189
190   //! Move forward
191   NCollection_StlIterator& operator+= (typename NCollection_StlIterator::difference_type theOffset)
192   {
193     Standard_STATIC_ASSERT((opencascade::is_same<std::random_access_iterator_tag,Category>::value));
194     myIterator.Offset (theOffset);
195     return *this;
196   }
197
198   //! Addition
199   NCollection_StlIterator operator+ (typename NCollection_StlIterator::difference_type theOffset) const
200   {
201     NCollection_StlIterator aTemp (*this);
202     return aTemp += theOffset;
203   }
204
205   //! Move backward
206   NCollection_StlIterator& operator-= (typename NCollection_StlIterator::difference_type theOffset)
207   {
208     return *this += -theOffset;
209   }
210
211   //! Decrease
212   NCollection_StlIterator operator- (typename NCollection_StlIterator::difference_type theOffset) const
213   {
214     NCollection_StlIterator aTemp (*this);
215     return aTemp += -theOffset;
216   }
217
218   //! Difference
219   typename NCollection_StlIterator::difference_type operator- (const NCollection_StlIterator& theOther) const
220   {
221     Standard_STATIC_ASSERT((opencascade::is_same<std::random_access_iterator_tag,Category>::value));
222     return myIterator.Differ (theOther.myIterator);
223   }
224
225   //! Get item at offset from current
226   typename NCollection_StlIterator::reference operator[] (typename NCollection_StlIterator::difference_type theOffset) const
227   {
228     return *(*this + theOffset);
229   }
230   
231   //! Comparison
232   bool operator< (const NCollection_StlIterator& theOther) const
233   {
234     return (*this - theOther) < 0;
235   }
236
237   //! Comparison
238   bool operator> (const NCollection_StlIterator& theOther) const
239   {
240     return theOther < *this;
241   }
242
243   //! Comparison
244   bool operator<= (const NCollection_StlIterator& theOther) const
245   {
246     return !(theOther < *this);
247   }
248
249   //! Comparison
250   bool operator>= (const NCollection_StlIterator& theOther) const
251   {
252     return !(*this < theOther);
253   }
254
255 private:
256   //! NCollection iterator
257   BaseIterator myIterator;
258 };
259
260 #endif // NCollection_StlIterator_HeaderFile