VTK  9.1.0
vtkDataArrayTupleRange_AOS.h
Go to the documentation of this file.
1/*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkDataArrayTupleRange_AOS.h
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14=========================================================================*/
19#ifndef vtkDataArrayTupleRange_AOS_h
20#define vtkDataArrayTupleRange_AOS_h
21
23#include "vtkDataArrayMeta.h"
25#include "vtkDebugRangeIterators.h"
26
27#include <algorithm>
28#include <cassert>
29#include <iterator>
30#include <type_traits>
31
32#ifndef __VTK_WRAP__
33
34// Disable this specialization when iterator debugging is requested:
35#ifndef VTK_DEBUG_RANGE_ITERATORS
36
38
39namespace vtk
40{
41
42namespace detail
43{
44
45// Forward decs for friends/args
46template <typename ArrayType, ComponentIdType>
47struct ConstTupleReference;
48template <typename ArrayType, ComponentIdType>
49struct TupleReference;
50template <typename ArrayType, ComponentIdType>
51struct ConstTupleIterator;
52template <typename ArrayType, ComponentIdType>
53struct TupleIterator;
54template <typename ArrayType, ComponentIdType>
55struct TupleRange;
56
57//------------------------------------------------------------------------------
58// Const tuple reference
59template <typename ValueType, ComponentIdType TupleSize>
60struct ConstTupleReference<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
61{
62private:
65 using APIType = ValueType;
66
67public:
69 using value_type = APIType;
70 using const_reference = const ValueType&;
71 using iterator = const ValueType*;
72 using const_iterator = const ValueType*;
73
76 : Tuple{ nullptr }
77 {
78 }
79
81 ConstTupleReference(const ValueType* tuple, NumCompsType numComps) noexcept
82 : Tuple(tuple)
83 , NumComps(numComps)
84 {
85 }
86
89 : Tuple{ o.Tuple }
90 , NumComps{ o.NumComps }
91 {
92 }
93
95 ConstTupleReference(const ConstTupleReference&) noexcept = default;
98
99 // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
101 ConstTupleReference* operator->() noexcept { return this; }
103 const ConstTupleReference* operator->() const noexcept { return this; }
104
105 // Caller must ensure that there are size() elements in array.
106 VTK_ITER_INLINE void GetTuple(volatile APIType* tuple) const noexcept
107 {
108 // Yes, the tuple argument is marked volatile. No, it's not a mistake.
109 //
110 // `volatile`'s intended usage per the standard is to disable optimizations
111 // when accessing a variable. Without it, GCC 8 will optimize the following
112 // loop to memcpy, but we're usually copying small tuples here, and the
113 // call to memcpy is more expensive than just doing an inline copy. By
114 // disabling the memcpy optimization, benchmarks are 60% faster when
115 // iterating with the Get/SetTuple methods, and are comparable to other
116 // methods of array access.
117 VTK_ITER_ASSUME(this->NumComps.value > 0);
118 for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
119 {
120 tuple[i] = this->Tuple[i];
121 }
122 }
123
124 // skips some runtime checks when both sizes are fixed:
125 template <typename OArrayType, ComponentIdType OSize>
127 const TupleReference<OArrayType, OSize>& other) const noexcept
128 {
129 // Check that types are convertible:
130 using OAPIType = GetAPIType<OArrayType>;
131 static_assert(
132 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
133
134 // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
135 static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
136
137 return std::equal(this->cbegin(), this->cend(), other.cbegin());
138 }
139
140 // Needs a runtime check:
141 template <typename OArrayType, ComponentIdType OSize>
143 const TupleReference<OArrayType, OSize>& other) const noexcept
144 {
145 // Check that types are convertible:
146 using OAPIType = GetAPIType<OArrayType>;
147 static_assert(
148 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
149
150 // Need to check the size at runtime :-(
151 if (other.size() != this->NumComps.value)
152 {
153 return false;
154 }
155
156 return std::equal(this->cbegin(), this->cend(), other.cbegin());
157 }
158
159 // skips some runtime checks when both sizes are fixed:
160 template <typename OArrayType, ComponentIdType OSize>
162 const ConstTupleReference<OArrayType, OSize>& other) const noexcept
163 {
164 // Check that types are convertible:
165 using OAPIType = GetAPIType<OArrayType>;
166 static_assert(
167 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
168
169 // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
170 static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
171
172 return std::equal(this->cbegin(), this->cend(), other.cbegin());
173 }
174
175 // Needs a runtime check:
176 template <typename OArrayType, ComponentIdType OSize>
178 const ConstTupleReference<OArrayType, OSize>& other) const noexcept
179 {
180 // Check that types are convertible:
181 using OAPIType = GetAPIType<OArrayType>;
182 static_assert(
183 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
184
185 // Need to check the size at runtime :-(
186 if (other.size() != this->NumComps.value)
187 {
188 return false;
189 }
190
191 return std::equal(this->cbegin(), this->cend(), other.cbegin());
192 }
193
194 template <typename OArrayType, ComponentIdType OSize>
196 {
197 return !(*this == o);
198 }
199
200 template <typename OArray, ComponentIdType OSize>
202 {
203 return !(*this == o);
204 }
205
207 const_reference operator[](size_type i) const noexcept { return this->Tuple[i]; }
208
210 size_type size() const noexcept { return this->NumComps.value; }
211
213 const_iterator begin() const noexcept { return const_iterator{ this->Tuple }; }
214
216 const_iterator end() const noexcept
217 {
218 return const_iterator{ this->Tuple + this->NumComps.value };
219 }
220
222 const_iterator cbegin() const noexcept { return const_iterator{ this->Tuple }; }
223
225 const_iterator cend() const noexcept
226 {
227 return const_iterator{ this->Tuple + this->NumComps.value };
228 }
229
230 friend struct ConstTupleIterator<ArrayType, TupleSize>;
231
232protected:
233 // Intentionally hidden:
236
237 const ValueType* Tuple;
239};
240
241//------------------------------------------------------------------------------
242// Tuple reference
243template <typename ValueType, ComponentIdType TupleSize>
244struct TupleReference<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
245{
246private:
249 using APIType = ValueType;
250
251public:
253 using value_type = APIType;
254 using iterator = ValueType*;
255 using const_iterator = const ValueType*;
256 using reference = ValueType&;
257 using const_reference = ValueType const&;
258
260 TupleReference() noexcept
261 : Tuple{ nullptr }
262 {
263 }
264
266 TupleReference(ValueType* tuple, NumCompsType numComps) noexcept
267 : Tuple(tuple)
268 , NumComps(numComps)
269 {
270 }
271
273 TupleReference(const TupleReference&) noexcept = default;
275 TupleReference(TupleReference&&) noexcept = default;
276
277 // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
279 TupleReference* operator->() noexcept { return this; }
281 const TupleReference* operator->() const noexcept { return this; }
282
283 // Caller must ensure that there are size() elements in array.
285 void GetTuple(volatile APIType* tuple) const noexcept
286 {
287 // Yes, the tuple argument is marked volatile. No, it's not a mistake.
288 //
289 // `volatile`'s intended usage per the standard is to disable optimizations
290 // when accessing a variable. Without it, GCC 8 will optimize the following
291 // loop to memcpy, but we're usually copying small tuples here, and the
292 // call to memcpy is more expensive than just doing an inline copy. By
293 // disabling the memcpy optimization, benchmarks are 60% faster when
294 // iterating with the Get/SetTuple methods, and are comparable to other
295 // methods of array access.
296 VTK_ITER_ASSUME(this->NumComps.value > 0);
297 for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
298 {
299 tuple[i] = this->Tuple[i];
300 }
301 }
302
303 // Caller must ensure that there are size() elements in array.
305 void SetTuple(const APIType* tuple) noexcept
306 {
307 volatile APIType* out = this->Tuple;
308 // Yes, this variable argument is marked volatile. See the explanation in
309 // GetTuple.
310 VTK_ITER_ASSUME(this->NumComps.value > 0);
311 for (ComponentIdType i = 0; i < this->NumComps.value; ++i)
312 {
313 out[i] = tuple[i];
314 }
315 }
316
319 {
320 std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
321 return *this;
322 }
323
324 template <typename OArrayType, ComponentIdType OSize>
326 const TupleReference<OArrayType, OSize>& other) noexcept
327 {
328 // Check that types are convertible:
329 using OAPIType = GetAPIType<OArrayType>;
330 static_assert(
331 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
332
333 // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
334 static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
335
336 std::copy_n(other.cbegin(), OSize, this->begin());
337 return *this;
338 }
339
340 template <typename OArrayType, ComponentIdType OSize>
342 const TupleReference<OArrayType, OSize>& other) noexcept
343 {
344 // Check that types are convertible:
345 using OAPIType = GetAPIType<OArrayType>;
346 static_assert(
347 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
348
349 // Note that the sizes are not checked here. Enable
350 // VTK_DEBUG_RANGE_ITERATORS to enable check.
351 std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
352 return *this;
353 }
354
355 template <typename OArrayType, ComponentIdType OSize>
357 const ConstTupleReference<OArrayType, OSize>& other) noexcept
358 {
359 // Check that types are convertible:
360 using OAPIType = GetAPIType<OArrayType>;
361 static_assert(
362 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
363
364 // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
365 static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
366
367 std::copy_n(other.cbegin(), OSize, this->begin());
368 return *this;
369 }
370
371 template <typename OArrayType, ComponentIdType OSize>
373 const ConstTupleReference<OArrayType, OSize>& other) noexcept
374 {
375 // Check that types are convertible:
376 using OAPIType = GetAPIType<OArrayType>;
377 static_assert(
378 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
379
380 // Note that the sizes are not checked here. Enable
381 // VTK_DEBUG_RANGE_ITERATORS to enable check.
382 std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
383 return *this;
384 }
385
386 // skips some runtime checks when both sizes are fixed:
387 template <typename OArrayType, ComponentIdType OSize>
389 const TupleReference<OArrayType, OSize>& other) const noexcept
390 {
391 // Check that types are convertible:
392 using OAPIType = GetAPIType<OArrayType>;
393 static_assert(
394 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
395
396 // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
397 static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
398
399 return std::equal(this->cbegin(), this->cend(), other.cbegin());
400 }
401
402 // Needs a runtime check:
403 template <typename OArrayType, ComponentIdType OSize>
405 const TupleReference<OArrayType, OSize>& other) const noexcept
406 {
407 // Check that types are convertible:
408 using OAPIType = GetAPIType<OArrayType>;
409 static_assert(
410 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
411
412 // Note that the sizes are not checked here. Enable
413 // VTK_DEBUG_RANGE_ITERATORS to enable check.
414 return std::equal(this->cbegin(), this->cend(), other.cbegin());
415 }
416
417 // skips some runtime checks when both sizes are fixed:
418 template <typename OArrayType, ComponentIdType OSize>
420 const ConstTupleReference<OArrayType, OSize>& other) const noexcept
421 {
422 // Check that types are convertible:
423 using OAPIType = GetAPIType<OArrayType>;
424 static_assert(
425 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
426
427 // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
428 static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
429
430 return std::equal(this->cbegin(), this->cend(), other.cbegin());
431 }
432
433 // Needs a runtime check:
434 template <typename OArrayType, ComponentIdType OSize>
436 const ConstTupleReference<OArrayType, OSize>& other) const noexcept
437 {
438 // Check that types are convertible:
439 using OAPIType = GetAPIType<OArrayType>;
440 static_assert(
441 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
442
443 // Note that the sizes are not checked here. Enable
444 // VTK_DEBUG_RANGE_ITERATORS to enable check.
445 return std::equal(this->cbegin(), this->cend(), other.cbegin());
446 }
447
448 template <typename OArrayType, ComponentIdType OSize>
450 {
451 return !(*this == o);
452 }
453
454 template <typename OArray, ComponentIdType OSize>
456 {
457 return !(*this == o);
458 }
459
460 // skips some runtime checks:
461 template <typename OArrayType, ComponentIdType OSize>
464 {
465 // Check that types are convertible:
466 using OAPIType = GetAPIType<OArrayType>;
467 static_assert((std::is_same<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
468
469 // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
470 static_assert(TupleSize == OSize, "Cannot swap tuples with different sizes.");
471
472 std::swap_ranges(this->begin(), this->end(), other.begin());
473 }
474
475 // Needs a runtime check:
476 template <typename OArrayType, ComponentIdType OSize>
479 {
480 // Check that types are convertible:
481 using OAPIType = GetAPIType<OArrayType>;
482 static_assert((std::is_same<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
483
484 // Note that the sizes are not checked here. Enable
485 // VTK_DEBUG_RANGE_ITERATORS to enable check.
486 std::swap_ranges(this->begin(), this->end(), other.begin());
487 }
488
489 friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept { a.swap(b); }
490
491 template <typename OArray, ComponentIdType OSize>
493 {
494 a.swap(b);
495 }
496
498 reference operator[](size_type i) noexcept { return this->Tuple[i]; }
499
501 const_reference operator[](size_type i) const noexcept { return this->Tuple[i]; }
502
504 void fill(const value_type& v) noexcept { std::fill(this->begin(), this->end(), v); }
505
507 size_type size() const noexcept { return this->NumComps.value; }
508
510 iterator begin() noexcept { return iterator{ this->Tuple }; }
511
513 iterator end() noexcept { return iterator{ this->Tuple + this->NumComps.value }; }
514
516 const_iterator begin() const noexcept { return const_iterator{ this->Tuple }; }
517
519 const_iterator end() const noexcept
520 {
521 return const_iterator{ this->Tuple + this->NumComps.value };
522 }
523
525 const_iterator cbegin() const noexcept { return const_iterator{ this->Tuple }; }
526
528 const_iterator cend() const noexcept
529 {
530 return const_iterator{ this->Tuple + this->NumComps.value };
531 }
532
533 friend struct ConstTupleReference<ArrayType, TupleSize>;
534 friend struct TupleIterator<ArrayType, TupleSize>;
535
536protected:
538 void CopyReference(const TupleReference& o) noexcept
539 {
540 this->Tuple = o.Tuple;
541 this->NumComps = o.NumComps;
542 }
543
544 ValueType* Tuple;
546};
547
548//------------------------------------------------------------------------------
549// Const tuple iterator
550template <typename ValueType, ComponentIdType TupleSize>
551struct ConstTupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
552{
553private:
556
557public:
558 using iterator_category = std::random_access_iterator_tag;
563
565 ConstTupleIterator() noexcept = default;
566
568 ConstTupleIterator(const ValueType* tuple, NumCompsType numComps) noexcept
569 : Ref(tuple, numComps)
570 {
571 }
572
575 : Ref{ o.Ref }
576 {
577 }
578
580 ConstTupleIterator(const ConstTupleIterator& o) noexcept = default;
582 ConstTupleIterator& operator=(const ConstTupleIterator& o) noexcept = default;
583
585 ConstTupleIterator& operator++() noexcept // prefix
586 {
587 this->Ref.Tuple += this->Ref.NumComps.value;
588 return *this;
589 }
590
592 ConstTupleIterator operator++(int) noexcept // postfix
593 {
594 auto tuple = this->Ref.Tuple;
595 this->Ref.Tuple += this->Ref.NumComps.value;
596 return ConstTupleIterator{ tuple, this->Ref.NumComps };
597 }
598
600 ConstTupleIterator& operator--() noexcept // prefix
601 {
602 this->Ref.Tuple -= this->Ref.NumComps.value;
603 return *this;
604 }
605
607 ConstTupleIterator operator--(int) noexcept // postfix
608 {
609 auto tuple = this->Ref.Tuple;
610 this->Ref.Tuple -= this->Ref.NumComps.value;
611 return ConstTupleIterator{ tuple, this->Ref.NumComps };
612 }
613
616 {
617 return reference{ this->Ref.Tuple + i * this->Ref.NumComps, this->Ref.NumComps };
618 }
619
621 reference operator*() noexcept { return this->Ref; }
622
624 pointer& operator->() noexcept { return this->Ref; }
625
626#define VTK_TMP_MAKE_OPERATOR(OP) \
627 friend VTK_ITER_INLINE bool operator OP( \
628 const ConstTupleIterator& lhs, const ConstTupleIterator& rhs) noexcept \
629 { \
630 return lhs.GetTuple() OP rhs.GetTuple(); \
631 }
632
639
640#undef VTK_TMP_MAKE_OPERATOR
641
644 {
645 this->Ref.Tuple += offset * this->Ref.NumComps.value;
646 return *this;
647 }
648
650 const ConstTupleIterator& it, difference_type offset) noexcept
651 {
652 return ConstTupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
653 }
654
656 difference_type offset, const ConstTupleIterator& it) noexcept
657 {
658 return ConstTupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
659 }
660
663 {
664 this->Ref.Tuple -= offset * this->Ref.NumComps.value;
665 return *this;
666 }
667
669 const ConstTupleIterator& it, difference_type offset) noexcept
670 {
671 return ConstTupleIterator{ it.GetTuple() - offset * it.GetNumComps().value, it.GetNumComps() };
672 }
673
675 const ConstTupleIterator& it1, const ConstTupleIterator& it2) noexcept
676 {
677 return static_cast<difference_type>(
678 (it1.GetTuple() - it2.GetTuple()) / it1.GetNumComps().value);
679 }
680
682 {
683 using std::swap;
684 swap(lhs.GetTuple(), rhs.GetTuple());
685 swap(lhs.GetNumComps(), rhs.GetNumComps());
686 }
687
688private:
690 const ValueType*& GetTuple() noexcept { return this->Ref.Tuple; }
692 const ValueType* GetTuple() const noexcept { return this->Ref.Tuple; }
694 NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
696 NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
697
698 ConstTupleReference<ArrayType, TupleSize> Ref;
699};
700
701//------------------------------------------------------------------------------
702// Tuple iterator
703template <typename ValueType, ComponentIdType TupleSize>
704struct TupleIterator<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
705{
706private:
709
710public:
711 using iterator_category = std::random_access_iterator_tag;
716
718 TupleIterator() noexcept = default;
719
721 TupleIterator(ValueType* tuple, NumCompsType numComps) noexcept
722 : Ref(tuple, numComps)
723 {
724 }
725
727 TupleIterator(const TupleIterator& o) noexcept = default;
728
731 {
732 this->Ref.CopyReference(o.Ref);
733 return *this;
734 }
735
737 TupleIterator& operator++() noexcept // prefix
738 {
739 this->Ref.Tuple += this->Ref.NumComps.value;
740 return *this;
741 }
742
744 TupleIterator operator++(int) noexcept // postfix
745 {
746 auto tuple = this->Ref.Tuple;
747 this->Ref.Tuple += this->Ref.NumComps.value;
748 return TupleIterator{ tuple, this->Ref.NumComps };
749 }
750
752 TupleIterator& operator--() noexcept // prefix
753 {
754 this->Ref.Tuple -= this->Ref.NumComps.value;
755 return *this;
756 }
757
759 TupleIterator operator--(int) noexcept // postfix
760 {
761 auto tuple = this->Ref.Tuple;
762 this->Ref.Tuple -= this->Ref.NumComps.value;
763 return TupleIterator{ tuple, this->Ref.NumComps };
764 }
765
768 {
769 return reference{ this->Ref.Tuple + i * this->Ref.NumComps.value, this->Ref.NumComps };
770 }
771
772 reference operator*() noexcept { return this->Ref; }
773
774 pointer& operator->() noexcept { return this->Ref; }
775
776#define VTK_TMP_MAKE_OPERATOR(OP) \
777 friend VTK_ITER_INLINE bool operator OP( \
778 const TupleIterator& lhs, const TupleIterator& rhs) noexcept \
779 { \
780 return lhs.GetTuple() OP rhs.GetTuple(); \
781 }
782
789
790#undef VTK_TMP_MAKE_OPERATOR
791
794 {
795 this->Ref.Tuple += offset * this->Ref.NumComps.value;
796 return *this;
797 }
798
800 const TupleIterator& it, difference_type offset) noexcept
801 {
802 return TupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
803 }
804
806 difference_type offset, const TupleIterator& it) noexcept
807 {
808 return TupleIterator{ it.GetTuple() + offset * it.GetNumComps().value, it.GetNumComps() };
809 }
810
813 {
814 this->Ref.Tuple -= offset * this->Ref.NumComps.value;
815 return *this;
816 }
817
819 const TupleIterator& it, difference_type offset) noexcept
820 {
821 return TupleIterator{ it.GetTuple() - offset * it.GetNumComps().value, it.GetNumComps() };
822 }
823
825 const TupleIterator& it1, const TupleIterator& it2) noexcept
826 {
827 return static_cast<difference_type>(
828 (it1.GetTuple() - it2.GetTuple()) / it1.GetNumComps().value);
829 }
830
831 friend VTK_ITER_INLINE void swap(TupleIterator& lhs, TupleIterator& rhs) noexcept
832 {
833 using std::swap;
834 swap(lhs.GetTuple(), rhs.GetTuple());
835 swap(lhs.GetNumComps(), rhs.GetNumComps());
836 }
837
838 friend struct ConstTupleIterator<ArrayType, TupleSize>;
839
840protected:
842 ValueType* GetTuple() const noexcept { return this->Ref.Tuple; }
844 ValueType*& GetTuple() noexcept { return this->Ref.Tuple; }
846 NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
848 NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
849
851};
852
853//------------------------------------------------------------------------------
854// Tuple range
855template <typename ValueType, ComponentIdType TupleSize>
856struct TupleRange<vtkAOSDataArrayTemplate<ValueType>, TupleSize>
857{
860
861private:
862 static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
863 static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
864
866
867public:
877
883
884 // May be DynamicTupleSize, or the actual tuple size.
885 constexpr static ComponentIdType TupleSizeTag = TupleSize;
886
888 TupleRange() noexcept = default;
889
891 TupleRange(ArrayType* arr, TupleIdType beginTuple, TupleIdType endTuple) noexcept
892 : Array(arr)
893 , NumComps(arr)
894 , BeginTuple(TupleRange::GetTuplePointer(arr, beginTuple))
895 , EndTuple(TupleRange::GetTuplePointer(arr, endTuple))
896 {
897 assert(this->Array);
898 assert(beginTuple >= 0 && beginTuple <= endTuple);
899 assert(endTuple >= 0 && endTuple <= this->Array->GetNumberOfTuples());
900 }
901
903 TupleRange GetSubRange(TupleIdType beginTuple = 0, TupleIdType endTuple = -1) const noexcept
904 {
905 const TupleIdType curBegin = this->GetTupleId(this->BeginTuple);
906 const TupleIdType realBegin = curBegin + beginTuple;
907 const TupleIdType realEnd =
908 endTuple >= 0 ? curBegin + endTuple : this->GetTupleId(this->EndTuple);
909
910 return TupleRange{ this->Array, realBegin, realEnd };
911 }
912
914 ArrayType* GetArray() const noexcept { return this->Array; }
915
917 ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
918
920 TupleIdType GetBeginTupleId() const noexcept { return this->GetTupleId(this->BeginTuple); }
921
923 TupleIdType GetEndTupleId() const noexcept { return this->GetTupleId(this->EndTuple); }
924
926 size_type size() const noexcept
927 {
928 return static_cast<size_type>(this->EndTuple - this->BeginTuple) /
929 static_cast<size_type>(this->NumComps.value);
930 }
931
933 iterator begin() noexcept { return iterator(this->BeginTuple, this->NumComps); }
934
936 iterator end() noexcept { return iterator(this->EndTuple, this->NumComps); }
937
939 const_iterator begin() const noexcept { return const_iterator(this->BeginTuple, this->NumComps); }
940
942 const_iterator end() const noexcept { return const_iterator(this->EndTuple, this->NumComps); }
943
945 const_iterator cbegin() const noexcept
946 {
947 return const_iterator(this->BeginTuple, this->NumComps);
948 }
949
951 const_iterator cend() const noexcept { return const_iterator(this->EndTuple, this->NumComps); }
952
955 {
956 return reference{ this->BeginTuple + i * this->NumComps.value, this->NumComps };
957 }
958
961 {
962 return const_reference{ this->BeginTuple + i * this->NumComps.value, this->NumComps };
963 }
964
965private:
967 ValueType* GetTuplePointer(ArrayType* array, vtkIdType tuple) const noexcept
968 {
969 return array->GetPointer(tuple * this->NumComps.value);
970 }
971
973 TupleIdType GetTupleId(const ValueType* ptr) const noexcept
974 {
975 return static_cast<TupleIdType>((ptr - this->Array->GetPointer(0)) / this->NumComps.value);
976 }
977
978 mutable ArrayType* Array{ nullptr };
979 NumCompsType NumComps{};
980 ValueType* BeginTuple{ nullptr };
981 ValueType* EndTuple{ nullptr };
982};
983
984// Unimplemented, only used inside decltype in SelectTupleRange:
985template <typename ArrayType, ComponentIdType TupleSize,
986 // Convenience:
987 typename ValueType = typename ArrayType::ValueType,
988 typename AOSArrayType = vtkAOSDataArrayTemplate<ValueType>,
989 // SFINAE to select AOS arrays:
992
993} // end namespace detail
994} // end namespace vtk
995
997
998#endif // VTK_DEBUG_RANGE_ITERATORS
999#endif // __VTK_WRAP__
1000#endif // vtkDataArrayTupleRange_AOS_h
1001
1002// VTK-HeaderTest-Exclude: vtkDataArrayTupleRange_AOS.h
Array-Of-Structs implementation of vtkGenericDataArray.
@ value
Definition: vtkX3D.h:226
@ type
Definition: vtkX3D.h:522
@ offset
Definition: vtkX3D.h:444
typename std::enable_if< AreStaticTupleSizes< S1, S2 >::value, T >::type EnableIfStaticTupleSizes
TupleRange< AOSArrayType, TupleSize > DeclareTupleRangeSpecialization(ArrayType *)
typename std::enable_if< IsEitherTupleSizeDynamic< S1, S2 >::value, T >::type EnableIfEitherTupleSizeIsDynamic
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
typename detail::GetAPITypeImpl< ArrayType >::APIType GetAPIType
vtkIdType TupleIdType
int ComponentIdType
friend VTK_ITER_INLINE void swap(ConstTupleIterator &lhs, ConstTupleIterator &rhs) noexcept
VTK_ITER_INLINE ConstTupleIterator & operator-=(difference_type offset) noexcept
friend VTK_ITER_INLINE ConstTupleIterator operator+(difference_type offset, const ConstTupleIterator &it) noexcept
friend VTK_ITER_INLINE ConstTupleIterator operator+(const ConstTupleIterator &it, difference_type offset) noexcept
friend VTK_ITER_INLINE ConstTupleIterator operator-(const ConstTupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE ConstTupleIterator & operator+=(difference_type offset) noexcept
VTK_ITER_INLINE ConstTupleIterator(const TupleIterator< ArrayType, TupleSize > &o) noexcept
friend VTK_ITER_INLINE difference_type operator-(const ConstTupleIterator &it1, const ConstTupleIterator &it2) noexcept
VTK_ITER_INLINE ConstTupleIterator & operator=(const ConstTupleIterator &o) noexcept=default
VTK_ITER_INLINE ConstTupleIterator(const ConstTupleIterator &o) noexcept=default
friend VTK_ITER_INLINE void swap(ConstTupleIterator &lhs, ConstTupleIterator &rhs) noexcept
VTK_ITER_INLINE bool operator!=(const ConstTupleReference< OArray, OSize > &o) const noexcept
VTK_ITER_INLINE ConstTupleReference(const ConstTupleReference &) noexcept=default
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE ConstTupleReference(ConstTupleReference &&) noexcept=default
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
VTK_ITER_INLINE ConstTupleReference & operator=(const ConstTupleReference &) noexcept=default
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE ConstTupleReference(const ValueType *tuple, NumCompsType numComps) noexcept
VTK_ITER_INLINE ConstTupleReference(const TupleReference< ArrayType, TupleSize > &o) noexcept
VTK_ITER_INLINE const_iterator cbegin() const noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
friend VTK_ITER_INLINE TupleIterator operator+(const TupleIterator &it, difference_type offset) noexcept
friend VTK_ITER_INLINE TupleIterator operator-(const TupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE TupleIterator & operator=(const TupleIterator &o) noexcept
VTK_ITER_INLINE TupleIterator(const TupleIterator &o) noexcept=default
friend VTK_ITER_INLINE TupleIterator operator+(difference_type offset, const TupleIterator &it) noexcept
VTK_ITER_INLINE TupleIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE TupleIterator & operator+=(difference_type offset) noexcept
friend VTK_ITER_INLINE difference_type operator-(const TupleIterator &it1, const TupleIterator &it2) noexcept
friend VTK_ITER_INLINE void swap(TupleIterator &lhs, TupleIterator &rhs) noexcept
TupleReference< ArrayType, TupleSize > Ref
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
VTK_ITER_INLINE TupleRange GetSubRange(TupleIdType beginTuple=0, TupleIdType endTuple=-1) const noexcept
static constexpr ComponentIdType TupleSizeTag
TupleIterator< ArrayType, TupleSize > TupleIteratorType
ConstTupleIterator< ArrayType, TupleSize > ConstTupleIteratorType
TupleReference< ArrayType, TupleSize > TupleReferenceType
ConstTupleReference< ArrayType, TupleSize > ConstTupleReferenceType
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, TupleReference & > operator=(const ConstTupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE TupleReference & operator=(const TupleReference &other) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, void > swap(TupleReference< OArrayType, OSize > other) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, void > swap(TupleReference< OArrayType, OSize > other) noexcept
friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept
VTK_ITER_INLINE void GetTuple(volatile APIType *tuple) const noexcept
VTK_ITER_INLINE TupleReference(ValueType *tuple, NumCompsType numComps) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, TupleReference & > operator=(const TupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, TupleReference & > operator=(const TupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, TupleReference & > operator=(const ConstTupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE TupleReference(const TupleReference &) noexcept=default
VTK_ITER_INLINE TupleReference(TupleReference &&) noexcept=default
friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference< OArray, OSize > b) noexcept
VTK_ITER_INLINE bool operator!=(const ConstTupleReference< OArray, OSize > &o) const noexcept
VTK_ITER_INLINE const_iterator cbegin() const noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
VTK_ITER_INLINE iterator begin() noexcept
VTK_ITER_INLINE iterator end() noexcept
This file contains a variety of metaprogramming constructs for working with vtkDataArrays.
#define VTK_ITER_OPTIMIZE_START
#define VTK_ITER_INLINE
#define VTK_ITER_OPTIMIZE_END
#define VTK_ITER_ASSUME
#define VTK_TMP_MAKE_OPERATOR(OP)
int vtkIdType
Definition: vtkType.h:332