0024911: Avoid using virtual functions in NCollection classes
[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 protected: //! @name methods related to forward STL iterator
105
106   // Note: Here we use SFINAE (Substitution failure is not an error) to choose
107   // an appropriate method based on template arguments (at instantiation time).
108
109   template<bool Condition>
110   typename opencascade::enable_if<!Condition, ItemType&>::type Reference()
111   {
112     return myIterator.ChangeValue();
113   }
114
115   template<bool Condition>
116   typename opencascade::enable_if<Condition, const ItemType&>::type Reference()
117   {
118     return myIterator.Value();
119   }
120
121 public: //! @name methods related to forward STL iterator
122
123   //! Test for equality
124   bool operator== (const NCollection_StlIterator& theOther) const
125   {
126     return myIterator.More() == theOther.myIterator.More() &&
127            (!myIterator.More() || myIterator.IsEqual (theOther.myIterator));
128   }
129
130   //! Test for inequality
131   bool operator!= (const NCollection_StlIterator& theOther) const
132   {
133     return !(*this == theOther);
134   }
135
136   //! Get reference to current item
137   typename NCollection_StlIterator::reference operator*()
138   {
139     return Reference<IsConstant>();
140   }
141
142   //! Dereferencing operator
143   typename NCollection_StlIterator::pointer operator->()
144   {
145     return &Reference<IsConstant>();
146   }
147
148   //! Prefix increment
149   NCollection_StlIterator& operator++()
150   {
151     myIterator.Next();
152     return *this;
153   }
154
155   //! Postfix increment
156   NCollection_StlIterator operator++(int)
157   {
158     const NCollection_StlIterator theOld (*this);
159     ++(*this);
160     return theOld;
161   }
162
163 public: //! @name methods related to bidirectional STL iterator
164   
165   //! Prefix decrement
166   NCollection_StlIterator& operator--()
167   {
168     Standard_STATIC_ASSERT((opencascade::is_same<std::bidirectional_iterator_tag,Category>::value ||
169                             opencascade::is_same<std::random_access_iterator_tag,Category>::value));
170     myIterator.Previous();
171     return *this;
172   }
173   
174   //! Postfix decrement
175   NCollection_StlIterator operator--(int)
176   {
177     NCollection_StlIterator theOld (*this);
178     --(*this);
179     return theOld;
180   }
181   
182 public: //! @name methods related to random access STL iterator
183
184   //! Move forward
185   NCollection_StlIterator& operator+= (typename NCollection_StlIterator::difference_type theOffset)
186   {
187     Standard_STATIC_ASSERT((opencascade::is_same<std::random_access_iterator_tag,Category>::value));
188     myIterator.Offset (theOffset);
189     return *this;
190   }
191
192   //! Addition
193   NCollection_StlIterator operator+ (typename NCollection_StlIterator::difference_type theOffset) const
194   {
195     NCollection_StlIterator aTemp (*this);
196     return aTemp += theOffset;
197   }
198
199   //! Move backward
200   NCollection_StlIterator& operator-= (typename NCollection_StlIterator::difference_type theOffset)
201   {
202     return *this += -theOffset;
203   }
204
205   //! Decrease
206   NCollection_StlIterator operator- (typename NCollection_StlIterator::difference_type theOffset) const
207   {
208     NCollection_StlIterator aTemp (*this);
209     return aTemp += -theOffset;
210   }
211
212   //! Difference
213   typename NCollection_StlIterator::difference_type operator- (const NCollection_StlIterator& theOther) const
214   {
215     Standard_STATIC_ASSERT((opencascade::is_same<std::random_access_iterator_tag,Category>::value));
216     return myIterator.Differ (theOther.myIterator);
217   }
218
219   //! Get item at offset from current
220   typename NCollection_StlIterator::reference operator[] (typename NCollection_StlIterator::difference_type theOffset) const
221   {
222     return *(*this + theOffset);
223   }
224   
225   //! Comparison
226   bool operator< (const NCollection_StlIterator& theOther) const
227   {
228     return (*this - theOther) < 0;
229   }
230
231   //! Comparison
232   bool operator> (const NCollection_StlIterator& theOther) const
233   {
234     return theOther < *this;
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 !(*this < theOther);
247   }
248
249 private:
250   //! NCollection iterator
251   BaseIterator myIterator;
252 };
253
254 #endif // NCollection_StlIterator_HeaderFile