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