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 itkFixedArray_h
19 #define itkFixedArray_h
20
21 #include "itkMacro.h"
22 #include <algorithm>
23 #include <array>
24
25 namespace itk
26 {
27
28 /** \class FixedArray
29 * \brief Simulate a standard C array with copy semantics.
30 *
31 * Simulates a standard C array, except that copy semantics are used instead
32 * of reference semantics. Also, arrays of different sizes cannot be
33 * assigned to one another, and size information is known for function
34 * returns.
35 *
36 * \tparam TValue Element type stored at each location in the array.
37 * \tparam VLength = Length of the array.
38 *
39 * The length of the array is fixed at compile time. If you wish to
40 * specify the length of the array at run-time, use the class itk::Array.
41 * If you wish to change to change the length of the array at run-time,
42 * you're best off using std::vector<>.
43 *
44 * \ingroup DataRepresentation
45 * \ingroup ITKCommon
46 *
47 * \wiki
48 * \wikiexample{Utilities/FixedArray,C-style array}
49 * \endwiki
50 */
51 template< typename TValue, unsigned int VLength = 3 >
52 class ITK_TEMPLATE_EXPORT FixedArray
53 {
54 public:
55 /** Length constant */
56 static constexpr unsigned int Length = VLength;
57
58 /** Dimension constant */
59 static constexpr unsigned int Dimension = VLength;
60
61 /** The element type stored at each location in the FixedArray. */
62 using ValueType = TValue;
63
64 /** A type representing the C-array version of this FixedArray. */
65 typedef ValueType CArray[VLength];
66
67 /** An iterator through the array. */
68 using Iterator = ValueType *;
69
70 /** A const iterator through the array. */
71 using ConstIterator = const ValueType *;
72
73 class ConstReverseIterator;
74
75 /** \class ReverseIterator
76 * \brief A reverse iterator through an array.
77 * \ingroup ITKCommon
78 */
79 class ReverseIterator
80 {
81 public:
ReverseIterator(Iterator i)82 explicit ReverseIterator(Iterator i):m_Iterator(i) {}
83 ReverseIterator operator++() { return ReverseIterator( --m_Iterator ); }
84 ReverseIterator operator++(int) { return ReverseIterator( m_Iterator-- ); }
85 ReverseIterator operator--() { return ReverseIterator( ++m_Iterator ); }
86 ReverseIterator operator--(int) { return ReverseIterator( m_Iterator++ ); }
87 Iterator operator->() const { return ( m_Iterator - 1 ); }
88 ValueType & operator*() const { return *( m_Iterator - 1 ); }
89 bool operator!=(const ReverseIterator & rit) const { return m_Iterator != rit.m_Iterator; }
90 bool operator==(const ReverseIterator & rit) const { return m_Iterator == rit.m_Iterator; }
91
92 private:
93 Iterator m_Iterator;
94 friend class ConstReverseIterator;
95 };
96
97 /** \class ConstReverseIterator
98 * \brief A const reverse iterator through an array.
99 * \ingroup ITKCommon
100 */
101 class ConstReverseIterator
102 {
103 public:
ConstReverseIterator(ConstIterator i)104 explicit ConstReverseIterator(ConstIterator i):m_Iterator(i) {}
ConstReverseIterator(const ReverseIterator & rit)105 ConstReverseIterator(const ReverseIterator & rit) { m_Iterator = rit.m_Iterator; }
106 ConstReverseIterator operator++() { return ConstReverseIterator( --m_Iterator ); }
107 ConstReverseIterator operator++(int) { return ConstReverseIterator( m_Iterator-- ); }
108 ConstReverseIterator operator--() { return ConstReverseIterator( ++m_Iterator ); }
109 ConstReverseIterator operator--(int) { return ConstReverseIterator( m_Iterator++ ); }
110 ConstIterator operator->() const { return ( m_Iterator - 1 ); }
111 const ValueType & operator*() const { return *( m_Iterator - 1 ); }
112 bool operator!=(const ConstReverseIterator & rit) const { return m_Iterator != rit.m_Iterator; }
113 bool operator==(const ConstReverseIterator & rit) const { return m_Iterator == rit.m_Iterator; }
114
115 private:
116 ConstIterator m_Iterator;
117 };
118
119 /** A pointer to the ValueType. */
120 using pointer = ValueType *;
121
122 /** A const pointer to the ValueType. */
123 using const_pointer = const ValueType *;
124
125 /** A reference to the ValueType. */
126 using reference = ValueType &;
127
128 /** A const reference to the ValueType. */
129 using const_reference = const ValueType &;
130
131 /** The return type of the non-const overloads of begin() and end(). */
132 using iterator = ValueType *;
133
134 /** The return type of cbegin() and cend(), and the const overloads of begin() and end(). */
135 using const_iterator = const ValueType *;
136
137 using reverse_iterator = std::reverse_iterator<iterator>;
138
139 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
140
141 using SizeType = unsigned int;
142
143 public:
144 /** Constructors */
145 FixedArray() = default;
146 FixedArray(const FixedArray &) = default;
147 FixedArray & operator=(const FixedArray & ) = default;
148 FixedArray(FixedArray &&) = default;
149 FixedArray & operator=(FixedArray && ) = default;
150 ~FixedArray() = default;
151
152 /** Conversion constructors */
153 FixedArray(const ValueType r[VLength]);
154 FixedArray(const ValueType & );
155
156 /** Explicit constructor for std::array. */
FixedArray(const std::array<ValueType,VLength> & stdArray)157 explicit FixedArray(const std::array<ValueType, VLength>& stdArray)
158 {
159 std::copy_n(stdArray.cbegin(), VLength, m_InternalArray);
160 }
161
162 /** Constructor to initialize a fixed array from another of any data type */
163 template< typename TFixedArrayValueType >
FixedArray(const FixedArray<TFixedArrayValueType,VLength> & r)164 FixedArray(const FixedArray< TFixedArrayValueType, VLength > & r)
165 {
166 auto input = r.cbegin();
167
168 for (auto& element : m_InternalArray)
169 {
170 element = static_cast< TValue >( *input++ );
171 }
172 }
173
174 template< typename TScalarValue >
FixedArray(const TScalarValue * r)175 FixedArray(const TScalarValue *r)
176 {
177 std::copy_n(r, VLength, m_InternalArray);
178 }
179
180 /** Operator= defined for a variety of types. */
181 template< typename TFixedArrayValueType >
182 FixedArray & operator=(const FixedArray< TFixedArrayValueType, VLength > & r)
183 {
184 auto input = r.cbegin();
185
186 for (auto& element : m_InternalArray)
187 {
188 element = static_cast< TValue >( *input++ );
189 }
190 return *this;
191 }
192
193 FixedArray & operator=(const ValueType r[VLength]);
194
195 /** Operators == and != are used to compare whether two arrays are equal.
196 * Note that arrays are equal when the number of components (size) is the
197 * same, and each component value is equal. */
198 bool operator==(const FixedArray & r) const;
199
200 bool operator!=(const FixedArray & r) const
201 { return !operator==(r); }
202
203 /** Allow the FixedArray to be indexed normally. No bounds checking is done.
204 * The separate versions are a work-around for an integer conversion bug in
205 * Visual C++. */
206 reference operator[](short index) { return m_InternalArray[index]; }
207 const_reference operator[](short index) const { return m_InternalArray[index]; }
208 reference operator[](unsigned short index) { return m_InternalArray[index]; }
209 const_reference operator[](unsigned short index) const { return m_InternalArray[index]; }
210 reference operator[](int index) { return m_InternalArray[index]; }
211 const_reference operator[](int index) const { return m_InternalArray[index]; }
212 // false positive warnings with GCC
213 #if defined( __GNUC__ )
214 #if ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ == 9 ) || ( __GNUC__ >= 7 )
215 #pragma GCC diagnostic push
216 #pragma GCC diagnostic ignored "-Warray-bounds"
217 #endif
218 #endif
219 reference operator[](unsigned int index) { return m_InternalArray[index]; }
220 const_reference operator[](unsigned int index) const { return m_InternalArray[index]; }
221 #if defined( __GNUC__ )
222 #if ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ == 9 ) || ( __GNUC__ >= 7 )
223 #pragma GCC diagnostic pop
224 #endif
225 #endif
226 reference operator[](long index) { return m_InternalArray[index]; }
227 const_reference operator[](long index) const { return m_InternalArray[index]; }
228 reference operator[](unsigned long index) { return m_InternalArray[index]; }
229 const_reference operator[](unsigned long index) const { return m_InternalArray[index]; }
230 reference operator[](long long index) { return m_InternalArray[index]; }
231 const_reference operator[](long long index) const { return m_InternalArray[index]; }
232 reference operator[](unsigned long long index) { return m_InternalArray[index]; }
233 const_reference operator[](unsigned long long index) const { return m_InternalArray[index]; }
234
235 /** Set/Get element methods are more convenient in wrapping languages */
SetElement(unsigned int index,const_reference value)236 void SetElement(unsigned int index, const_reference value)
237 { m_InternalArray[index] = value; }
GetElement(unsigned int index)238 const_reference GetElement(unsigned int index) const { return m_InternalArray[index]; }
239
240 /** Return a pointer to the data. */
GetDataPointer()241 ValueType * GetDataPointer()
242 {
243 return m_InternalArray;
244 }
245
GetDataPointer()246 const ValueType * GetDataPointer() const
247 {
248 return m_InternalArray;
249 }
250
251 /** Get various iterators to the array. */
252 Iterator Begin();
253
254 ConstIterator Begin() const;
255
256 Iterator End();
257
258 ConstIterator End() const;
259
260 itkLegacyMacro(ReverseIterator rBegin());
261
262 itkLegacyMacro(ConstReverseIterator rBegin() const);
263
264 itkLegacyMacro(ReverseIterator rEnd());
265
266 itkLegacyMacro(ConstReverseIterator rEnd() const);
267
cbegin()268 const_iterator cbegin() const noexcept
269 {
270 return m_InternalArray;
271 }
272
begin()273 iterator begin() noexcept
274 {
275 return m_InternalArray;
276 }
277
begin()278 const_iterator begin() const noexcept
279 {
280 return this->cbegin();
281 }
282
cend()283 const_iterator cend() const noexcept
284 {
285 return m_InternalArray + VLength;
286 }
287
end()288 iterator end() noexcept
289 {
290 return m_InternalArray + VLength;
291 }
292
end()293 const_iterator end() const noexcept
294 {
295 return this->cend();
296 }
297
rbegin()298 reverse_iterator rbegin()
299 {
300 return reverse_iterator{ this->end() };
301 }
302
crbegin()303 const_reverse_iterator crbegin() const
304 {
305 return const_reverse_iterator{ this->cend() };
306 }
307
rbegin()308 const_reverse_iterator rbegin() const
309 {
310 return this->crbegin();
311 }
312
rend()313 reverse_iterator rend()
314 {
315 return reverse_iterator{ this->begin() };
316 }
317
crend()318 const_reverse_iterator crend() const
319 {
320 return const_reverse_iterator{ this->cbegin() };
321 }
322
rend()323 const_reverse_iterator rend() const
324 {
325 return this->crend();
326 }
327
328 SizeType Size() const;
329
330 void Fill(const ValueType &);
331
swap(FixedArray & other)332 void swap(FixedArray &other)
333 {
334 std::swap(m_InternalArray, other.m_InternalArray);
335 }
336
337 private:
338 /** Internal C array representation. */
339 CArray m_InternalArray;
340
341 public:
342
343 static FixedArray Filled(const ValueType &);
344 };
345
346 template< typename TValue, unsigned int VLength >
347 std::ostream & operator<<(std::ostream & os, const FixedArray< TValue, VLength > & arr);
348
349
350 template< typename TValue, unsigned int VLength >
swap(FixedArray<TValue,VLength> & a,FixedArray<TValue,VLength> & b)351 inline void swap( FixedArray<TValue, VLength> &a, FixedArray<TValue, VLength> &b )
352 {
353 a.swap(b);
354 }
355
356 } // namespace itk
357
358 #ifndef ITK_MANUAL_INSTANTIATION
359 #include "itkFixedArray.hxx"
360 #endif
361
362 #include "itkNumericTraitsFixedArrayPixel.h"
363
364 #endif
365