1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkVectorContainer_h
19 #define itkVectorContainer_h
20 
21 #include "itkObject.h"
22 #include "itkObjectFactory.h"
23 
24 #include <utility>
25 #include <vector>
26 
27 namespace itk
28 {
29 /** \class VectorContainer
30  *  \brief Define a front-end to the STL "vector" container that conforms to the
31  *         IndexedContainerInterface.
32  *
33  * This is a full-fleged Object, so
34  * there is modification time, debug, and reference count information.
35  *
36  * \tparam TElementIdentifier An INTEGRAL type for use in indexing the vector.
37  *
38  * \tparam TElement The element type stored in the container.
39  *
40  * \ingroup DataRepresentation
41  * \ingroup ITKCommon
42  *
43  * \wiki
44  * \wikiexample{Utilities/VectorContainer,Vector container}
45  * \endwiki
46  */
47 template<
48   typename TElementIdentifier,
49   typename TElement
50   >
51 class ITK_TEMPLATE_EXPORT VectorContainer:
52   public Object,
53   private std::vector< TElement >
54 {
55 public:
56   /** Standard class type aliases. */
57   using Self = VectorContainer;
58   using Superclass = Object;
59   using Pointer = SmartPointer< Self >;
60   using ConstPointer = SmartPointer< const Self >;
61 
62   /** Save the template parameters. */
63   using ElementIdentifier = TElementIdentifier;
64   using Element = TElement;
65 
66 private:
67   /** Quick access to the STL vector type that was inherited. */
68   using VectorType = std::vector< Element >;
69   using size_type = typename VectorType::size_type;
70   using VectorIterator = typename VectorType::iterator;
71   using VectorConstIterator = typename VectorType::const_iterator;
72 
73 protected:
74   /** Provide pass-through constructors corresponding to all the STL
75    * vector constructors.  These are for internal use only since this is also
76    * an Object which must be constructed through the "New()" routine. */
VectorContainer()77   VectorContainer():
78     Object(), VectorType() {}
VectorContainer(size_type n)79   VectorContainer(size_type n):
80     Object(), VectorType(n) {}
VectorContainer(size_type n,const Element & x)81   VectorContainer(size_type n, const Element & x):
82     Object(), VectorType(n, x) {}
VectorContainer(const Self & r)83   VectorContainer(const Self & r):
84     Object(), VectorType(r.CastToSTLConstContainer()) {}
85   template< typename TInputIterator >
VectorContainer(TInputIterator first,TInputIterator last)86   VectorContainer(TInputIterator first, TInputIterator last):
87     Object(), VectorType(first, last) {}
88 
89 public:
90 
91   /** This type is provided to Adapt this container as an STL container */
92   using STLContainerType = VectorType;
93 
94   /** Method for creation through the object factory. */
95   itkNewMacro(Self);
96 
97   /** Standard part of every itk Object. */
98   itkTypeMacro(VectorContainer, Object);
99 
100   /** Convenient type alias for the iterator and const iterator. */
101   class Iterator;
102   class ConstIterator;
103 
104   /** Cast the container to a STL container type */
CastToSTLContainer()105   STLContainerType & CastToSTLContainer() ITK_NOEXCEPT
106   {
107     return *this;
108   }
109 
110   /** Cast the container to a const STL container type */
CastToSTLConstContainer()111   const STLContainerType & CastToSTLConstContainer() const ITK_NOEXCEPT
112   {
113     return *this;
114   }
115 
116   using STLContainerType::begin;
117   using STLContainerType::end;
118   using STLContainerType::rbegin;
119   using STLContainerType::rend;
120   using STLContainerType::cbegin;
121   using STLContainerType::cend;
122   using STLContainerType::crbegin;
123   using STLContainerType::crend;
124 
125   using STLContainerType::size;
126   using STLContainerType::max_size;
127   using STLContainerType::resize;
128   using STLContainerType::capacity;
129   using STLContainerType::empty;
130   using STLContainerType::reserve;
131   using STLContainerType::shrink_to_fit;
132 
133   using STLContainerType::operator[];
134   using STLContainerType::at;
135   using STLContainerType::front;
136   using STLContainerType::back;
137 
138   using STLContainerType::assign;
139   using STLContainerType::push_back;
140   using STLContainerType::pop_back;
141   using STLContainerType::insert;
142   using STLContainerType::erase;
143   using STLContainerType::swap;
144   using STLContainerType::clear;
145 
146   using STLContainerType::get_allocator;
147 
148   using typename STLContainerType::reference;
149   using typename STLContainerType::const_reference;
150   using typename STLContainerType::iterator;
151   using typename STLContainerType::const_iterator;
152   // already declared before
153   // using STLContainerType::size_type;
154   using typename STLContainerType::difference_type;
155   using typename STLContainerType::value_type;
156   using typename STLContainerType::allocator_type;
157   using typename STLContainerType::pointer;
158   using typename STLContainerType::const_pointer;
159   using typename STLContainerType::reverse_iterator;
160   using typename STLContainerType::const_reverse_iterator;
161 
162   /** Friends to this class. */
163   friend class Iterator;
164   friend class ConstIterator;
165 
166   /** \class Iterator
167    * Simulate STL-map style iteration where dereferencing the iterator
168    * gives access to both the index and the value.
169    * \ingroup ITKCommon
170    */
171   class Iterator
172   {
173 public:
174     using iterator_category = typename VectorIterator::iterator_category;
175     using value_type = typename VectorIterator::value_type;
176     using difference_type = typename VectorIterator::difference_type;
177     using pointer = typename VectorIterator::pointer;
178     using reference = typename VectorIterator::reference;
179 
Iterator()180     Iterator() : m_Pos(0) {}
Iterator(size_type d,const VectorIterator & i)181     Iterator(size_type d, const VectorIterator & i):m_Pos(d), m_Iter(i) {}
Iterator(const Iterator & r)182     Iterator(const Iterator & r): m_Pos(r.m_Pos), m_Iter(r.m_Iter) {}
183     Iterator & operator*()    { return *this; }
184     Iterator * operator->()   { return this; }
185     Iterator & operator++()   { ++m_Pos; ++m_Iter; return *this; }
186     Iterator operator++(int) { Iterator temp(*this); ++m_Pos; ++m_Iter; return temp; }
187     Iterator & operator--()   { --m_Pos; --m_Iter; return *this; }
188     Iterator operator--(int) { Iterator temp(*this); --m_Pos; --m_Iter; return temp; }
189 
190     difference_type operator-(const Iterator & r) const { return static_cast< difference_type >( this->m_Pos ) - static_cast< difference_type >( r.m_Pos ); }
191 
192     bool operator==(const Iterator & r) const { return m_Iter == r.m_Iter; }
193     bool operator!=(const Iterator & r) const { return m_Iter != r.m_Iter; }
194     bool operator==(const ConstIterator & r) const { return m_Iter == r.m_Iter; }
195     bool operator!=(const ConstIterator & r) const { return m_Iter != r.m_Iter; }
196     bool operator<(const Iterator & r) const { return ( this->operator-( r ) ) < 0; }
197     bool operator>(const Iterator & r) const { return ( r < *this ); }
198     bool operator>=(const Iterator & r) const { return !( *this < r ); }
199     bool operator<=(const Iterator & r) const { return !( *this < r ); }
200 
201     Iterator & operator+=(difference_type n) { m_Pos += n; m_Iter += n; return *this; };
202 
203     /** Get the index into the VectorContainer associated with this iterator.
204         */
Index()205     ElementIdentifier Index() const { return static_cast< ElementIdentifier >( m_Pos ); }
206 
207     /** Get the value at this iterator's location in the VectorContainer.   */
Value()208     reference Value() const { return *m_Iter; }
209 
210 private:
211     size_type      m_Pos;
212     VectorIterator m_Iter;
213     friend class ConstIterator;
214   };
215 
216   /** \class ConstIterator
217    * Simulate STL-map style const iteration where dereferencing the iterator
218    * gives read access to both the index and the value.
219    * \ingroup ITKCommon
220    */
221   class ConstIterator
222   {
223 public:
224     using iterator_category = typename VectorConstIterator::iterator_category;
225     using value_type = typename VectorConstIterator::value_type;
226     using difference_type = typename VectorConstIterator::difference_type;
227     using pointer = typename VectorConstIterator::pointer;
228     using reference = typename VectorConstIterator::reference;
229 
ConstIterator()230     ConstIterator():m_Pos(0) {}
ConstIterator(size_type d,const VectorConstIterator & i)231     ConstIterator(size_type d, const VectorConstIterator & i):m_Pos(d), m_Iter(i) {}
ConstIterator(const Iterator & r)232     ConstIterator(const Iterator & r) : m_Pos( r.m_Pos ), m_Iter( r.m_Iter ) { }
233     ConstIterator & operator*()    { return *this; }
234     ConstIterator * operator->()   { return this; }
235     ConstIterator & operator++()   { ++m_Pos; ++m_Iter; return *this; }
236     ConstIterator operator++(int) { ConstIterator temp(*this); ++m_Pos; ++m_Iter; return temp; }
237     ConstIterator & operator--()   { --m_Pos; --m_Iter; return *this; }
238     ConstIterator operator--(int) { ConstIterator temp(*this); --m_Pos; --m_Iter; return temp; }
239     ConstIterator & operator=(const Iterator & r) { m_Pos = r.m_Pos; m_Iter = r.m_Iter; return *this; }
240     ConstIterator & operator+=(difference_type n) { m_Pos += n; m_Iter += n; return *this; };
241 
242     difference_type operator-(const ConstIterator & r) const { return static_cast< difference_type >( m_Pos ) - static_cast< difference_type >( r.m_Pos ); }
243 
244     bool operator==(const Iterator & r) const { return m_Iter == r.m_Iter; }
245     bool operator!=(const Iterator & r) const { return m_Iter != r.m_Iter; }
246     bool operator==(const ConstIterator & r) const { return m_Iter == r.m_Iter; }
247     bool operator!=(const ConstIterator & r) const { return m_Iter != r.m_Iter; }
248     bool operator<(const ConstIterator & r) const { return ( this->operator-(r) < 0 ); }
249     bool operator>(const ConstIterator & r) const { return ( r < *this ); }
250     bool operator<=(const ConstIterator & r) const { return !( *this > r ); }
251     bool operator>=(const ConstIterator & r) const { return !( *this < r ); }
252 
253 
254     /** Get the index into the VectorContainer associated with this iterator.
255         */
Index()256     ElementIdentifier Index() const { return static_cast< ElementIdentifier >( m_Pos ); }
257     /** Get the value at this iterator's location in the VectorContainer.   */
Value()258     const_reference Value() const { return *m_Iter; }
259 
260 private:
261     size_type           m_Pos;
262     VectorConstIterator m_Iter;
263     friend class Iterator;
264   };
265 
266   /* Declare the public interface routines. */
267 
268   /**
269    * Get a reference to the element at the given index.
270    * It is assumed that the index exists, and it will not automatically
271    * be created.
272    *
273    * It is assumed that the value of the element is modified through the
274    * reference.
275    */
276   reference ElementAt(ElementIdentifier);
277 
278   /**
279    * Get a reference to the element at the given index.
280    * It is assumed that the index exists, and it will not automatically
281    * be created.
282    *
283    */
284   const_reference ElementAt(ElementIdentifier) const;
285 
286   /**
287    * Get a reference to the element at the given index.
288    * If the element location does not exist, it will be created with a
289    * default element value.
290    *
291    * It is assumed that the value of the element is modified through the
292    * reference.
293    */
294   reference CreateElementAt(ElementIdentifier);
295 
296   /**
297    * Read the element from the given index.
298    * It is assumed that the index exists.
299    */
300   Element GetElement(ElementIdentifier) const;
301 
302   /**
303    * Set the element value at the given index.
304    * It is assumed that the index exists.
305    */
306   void SetElement(ElementIdentifier, Element);
307 
308   /**
309    * Set the element value at the given index.
310    * If the element location does not exist, it will be created with a
311    * default element value.
312    */
313   void InsertElement(ElementIdentifier, Element);
314 
315   /**
316    * Check if the index range of the vector is large enough to allow the
317    * given index without expansion.
318    */
319   bool IndexExists(ElementIdentifier) const;
320 
321   /**
322    * Check if the given index is in range of the vector.  If it is not, return
323    * false.  Otherwise, set the element through the pointer (if it isn't nullptr),
324    * and return true.
325    */
326   bool GetElementIfIndexExists(ElementIdentifier, Element *) const;
327 
328   /**
329    * Make sure that the index range of the vector is large enough to allow
330    * the given index, expanding it if necessary.  The index will contain
331    * the default element regardless of whether expansion occurred.
332    */
333   void CreateIndex(ElementIdentifier);
334 
335   /**
336    * Delete the element defined by the index identifier.  In practice, it
337    * doesn't make sense to delete a vector index.  Instead, this method just
338    * overwrite the index with the default element.
339    */
340   void DeleteIndex(ElementIdentifier);
341 
342   /**
343    * Get a begin const iterator for the vector.
344    */
345   ConstIterator Begin() const;
346 
347   /**
348    * Get an end const iterator for the vector.
349    */
350   ConstIterator End() const;
351 
352   /**
353    * Get a begin iterator for the vector.
354    */
355   Iterator Begin();
356 
357   /**
358    * Get an end iterator for the vector.
359    */
360   Iterator End();
361 
362   /**
363    * Get the number of elements currently stored in the vector.
364    */
365   ElementIdentifier Size() const;
366 
367   /**
368    * Tell the container to allocate enough memory to allow at least as many
369    * elements as the size given to be stored.  In the generic case of ITK
370    * containers this is NOT guaranteed to actually allocate any memory, but it
371    * is useful if the implementation of the container allocates contiguous
372    * storage. In the particular implementation of this VectorContainer the call
373    * to this method actually allocates memory for the number of elements
374    * defined by ElementIdentifier.
375    */
376   void Reserve(ElementIdentifier);
377 
378   /**
379    * Tell the container to try to minimize its memory usage for storage of the
380    * current number of elements.  This is NOT guaranteed to decrease memory
381    * usage. This method is included here mainly for providing a unified API
382    * with other containers in the toolkit.
383    */
384   void Squeeze();
385 
386   /**
387    * Clear the elements. The final size will be zero.
388    */
389   void Initialize();
390 };
391 } // end namespace itk
392 
393 #ifndef ITK_MANUAL_INSTANTIATION
394 #include "itkVectorContainer.hxx"
395 #endif
396 
397 #endif
398