VTK  9.3.0
vtkDataArrayTupleRange_Generic.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
8 #ifndef vtkDataArrayTupleRange_Generic_h
9 #define vtkDataArrayTupleRange_Generic_h
10 
11 #include "vtkAssume.h"
12 #include "vtkDataArrayAccessor.h"
13 #include "vtkDataArrayMeta.h"
14 
15 #include <algorithm>
16 #include <cassert>
17 #include <iterator>
18 #include <type_traits>
19 
21 
22 namespace vtk
23 {
24 namespace detail
25 {
26 VTK_ABI_NAMESPACE_BEGIN
27 
28 // Forward decs for friends/args
29 template <typename ArrayType, ComponentIdType>
30 struct ConstComponentReference;
31 template <typename ArrayType, ComponentIdType>
32 struct ComponentReference;
33 template <typename ArrayType, ComponentIdType>
34 struct ConstComponentIterator;
35 template <typename ArrayType, ComponentIdType>
36 struct ComponentIterator;
37 template <typename ArrayType, ComponentIdType>
38 struct ConstTupleReference;
39 template <typename ArrayType, ComponentIdType>
40 struct TupleReference;
41 template <typename ArrayType, ComponentIdType>
42 struct ConstTupleIterator;
43 template <typename ArrayType, ComponentIdType>
44 struct TupleIterator;
45 template <typename ArrayType, ComponentIdType>
46 struct TupleRange;
47 
48 //------------------------------------------------------------------------------
49 // Const component reference
50 template <typename ArrayType, ComponentIdType TupleSize>
52 {
53 private:
54  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
55  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
56 
58  using APIType = GetAPIType<ArrayType>;
59 
60 public:
61  using value_type = APIType;
62 
65  : Array{ nullptr }
66  , NumComps{}
67  , TupleId{ 0 }
68  , ComponentId{ 0 }
69  {
70  }
71 
74  ArrayType* array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept
75  : Array{ array }
76  , NumComps{ numComps }
77  , TupleId{ tuple }
78  , ComponentId{ comp }
79  {
80  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
81  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
83  tuple >= 0 && tuple <= array->GetNumberOfTuples(), "Invalid tuple accessed by iterator.");
84  VTK_ITER_ASSERT(comp >= 0 && comp <= array->GetNumberOfComponents(),
85  "Invalid component accessed by iterator.");
86  }
87 
90  : Array{ o.Array }
91  , NumComps{ o.NumComps }
92  , TupleId{ o.TupleId }
94  {
95  }
96 
98  ConstComponentReference(const ConstComponentReference& o) noexcept = default;
99 
102 
105  {
106  VTK_ITER_ASSERT(!this->Array, "Const reference already initialized.");
107  // Initialize the reference.
108  this->Array = o.Array;
109  this->NumComps = o.NumComps;
110  this->TupleId = o.TupleId;
111  this->ComponentId = o.ComponentId;
112  }
113 
116  {
117  VTK_ITER_ASSERT(!this->Array, "Const reference already initialized.");
118  // Initialize the reference.
119  this->Array = std::move(o.Array);
120  this->NumComps = std::move(o.NumComps);
121  this->TupleId = std::move(o.TupleId);
122  this->ComponentId = std::move(o.ComponentId);
123  }
124 
126  operator APIType() const noexcept
127  {
128  VTK_ITER_ASSUME(this->NumComps.value > 0);
129  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
131  return acc.Get(this->TupleId, this->ComponentId);
132  }
133 
134 protected:
135  mutable ArrayType* Array;
139 };
140 
141 //------------------------------------------------------------------------------
142 // Component reference
143 template <typename ArrayType, ComponentIdType TupleSize>
145 {
146 private:
147  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
148  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
149 
151  using APIType = GetAPIType<ArrayType>;
152 
153 public:
154  using value_type = APIType;
155 
158  : Array{ nullptr }
159  , NumComps{}
160  , TupleId{ 0 }
161  , ComponentId{ 0 }
162  {
163  }
164 
167  ArrayType* array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept
168  : Array{ array }
169  , NumComps{ numComps }
170  , TupleId{ tuple }
171  , ComponentId{ comp }
172  {
173  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
174  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
176  tuple >= 0 && tuple <= array->GetNumberOfTuples(), "Invalid tuple accessed by iterator.");
177  VTK_ITER_ASSERT(comp >= 0 && comp <= array->GetNumberOfComponents(),
178  "Invalid component accessed by iterator.");
179  }
180 
182  ComponentReference(const ComponentReference& o) noexcept = default;
184  ComponentReference(ComponentReference&& o) noexcept = default;
185 
188  {
189  if (this->Array)
190  { // Already initialized. Assign the value, not the reference
191  return *this = static_cast<APIType>(o);
192  }
193  else
194  { // Initialize the reference.
195  this->Array = o.Array;
196  this->NumComps = o.NumComps;
197  this->TupleId = o.TupleId;
198  this->ComponentId = o.ComponentId;
199 
200  return *this;
201  }
202  }
203 
206  {
207  if (this->Array)
208  { // Already initialized. Assign the value, not the reference
209  return *this = std::move(static_cast<APIType>(o));
210  }
211  else
212  { // Initialize the reference.
213  this->Array = std::move(o.Array);
214  this->NumComps = std::move(o.NumComps);
215  this->TupleId = std::move(o.TupleId);
216  this->ComponentId = std::move(o.ComponentId);
217 
218  return *this;
219  }
220  }
221 
222  template <typename OArray, ComponentIdType OSize>
224  { // Always copy the value for different reference types:
225  const APIType tmp = o;
226  return *this = std::move(tmp);
227  }
228 
230  operator APIType() const noexcept
231  {
232  VTK_ITER_ASSUME(this->NumComps.value > 0);
233  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
235  return acc.Get(this->TupleId, this->ComponentId);
236  }
237 
239  ComponentReference operator=(APIType val) noexcept
240  {
241  VTK_ITER_ASSUME(this->NumComps.value > 0);
242  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
244  acc.Set(this->TupleId, this->ComponentId, val);
245  return *this;
246  }
247 
249  { // Swap values, not references:
250  APIType tmp = std::move(static_cast<APIType>(lhs));
251  lhs = std::move(static_cast<APIType>(rhs));
252  rhs = std::move(tmp);
253  }
254 
255  template <typename OArray, ComponentIdType OSize>
256  friend VTK_ITER_INLINE void swap(
258  { // Swap values, not references:
259  using OAPIType = GetAPIType<OArray>;
260  static_assert(
261  std::is_same<APIType, OAPIType>::value, "Cannot swap components with different types.");
262 
263  APIType tmp = std::move(static_cast<APIType>(lhs));
264  lhs = std::move(static_cast<APIType>(rhs));
265  rhs = std::move(tmp);
266  }
267 
268  friend VTK_ITER_INLINE void swap(ComponentReference lhs, APIType& rhs) noexcept
269  {
270  APIType tmp = std::move(static_cast<APIType>(lhs));
271  lhs = std::move(rhs);
272  rhs = std::move(tmp);
273  }
274 
275  friend VTK_ITER_INLINE void swap(APIType& lhs, ComponentReference rhs) noexcept
276  {
277  APIType tmp = std::move(lhs);
278  lhs = std::move(static_cast<APIType>(rhs));
279  rhs = std::move(tmp);
280  }
281 
283  ComponentReference operator++() noexcept // prefix
284  {
285  const APIType newVal = *this + 1;
286  *this = newVal;
287  return *this;
288  }
289 
291  APIType operator++(int) noexcept // postfix
292  {
293  const APIType retVal = *this;
294  *this = *this + 1;
295  return retVal;
296  }
297 
299  ComponentReference operator--() noexcept // prefix
300  {
301  const APIType newVal = *this - 1;
302  *this = newVal;
303  return *this;
304  }
305 
307  APIType operator--(int) noexcept // postfix
308  {
309  const APIType retVal = *this;
310  *this = *this - 1;
311  return retVal;
312  }
313 
314 #define VTK_REF_OP_OVERLOADS(Op, ImplOp) \
315  friend VTK_ITER_INLINE ComponentReference operator Op( \
316  ComponentReference lhs, APIType val) noexcept \
317  { \
318  const APIType newVal = lhs ImplOp val; \
319  lhs = newVal; \
320  return lhs; \
321  } \
322  friend VTK_ITER_INLINE ComponentReference operator Op( \
323  ComponentReference lhs, ComponentReference val) noexcept \
324  { \
325  const APIType newVal = lhs ImplOp val; \
326  lhs = newVal; \
327  return lhs; \
328  } \
329  friend VTK_ITER_INLINE APIType& operator Op(APIType& lhs, ComponentReference val) noexcept \
330  { \
331  const APIType newVal = lhs ImplOp val; \
332  lhs = newVal; \
333  return lhs; \
334  }
335 
336  VTK_REF_OP_OVERLOADS(+=, +)
337  VTK_REF_OP_OVERLOADS(-=, -)
338  VTK_REF_OP_OVERLOADS(*=, *)
339  VTK_REF_OP_OVERLOADS(/=, /)
340 
341 #undef VTK_REF_OP_OVERLOADS
342 
343  friend struct ConstComponentReference<ArrayType, TupleSize>;
344  friend struct ComponentIterator<ArrayType, TupleSize>;
345 
346 protected:
348  void CopyReference(const ComponentReference& o) noexcept
349  {
350  this->Array = o.Array;
351  this->NumComps = o.NumComps;
352  this->TupleId = o.TupleId;
353  this->ComponentId = o.ComponentId;
354  }
355 
356  mutable ArrayType* Array;
360 };
361 
362 //------------------------------------------------------------------------------
363 // Const component iterator
364 template <typename ArrayType, ComponentIdType TupleSize>
366 {
367 private:
368  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
369  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
370 
372 
373 public:
374  using iterator_category = std::random_access_iterator_tag;
377  using pointer = void;
379 
382  : Array{ nullptr }
383  , TupleId{ 0 }
384  , ComponentId{ 0 }
385  {
386  }
387 
390  ArrayType* array, NumCompsType numComps, TupleIdType tupleId, ComponentIdType comp) noexcept
391  : Array(array)
392  , NumComps(numComps)
393  , TupleId(tupleId)
394  , ComponentId(comp)
395  {
396  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
397  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
398  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
399  "Const component iterator at invalid tuple id.");
400  VTK_ITER_ASSERT(comp >= 0 && comp <= this->NumComps.value,
401  "Const component iterator at invalid component id.");
402  }
403 
406  : Array{ o.GetArray() }
407  , NumComps{ o.GetNumComps() }
408  , TupleId{ o.GetTupleId() }
409  , ComponentId{ o.GetComponentId() }
410  {
411  }
412 
414  ConstComponentIterator(const ConstComponentIterator& o) noexcept = default;
417 
419  ConstComponentIterator& operator++() noexcept // prefix
420  {
421  ++this->ComponentId;
422  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
423  "Const component iterator at invalid component id.");
424  return *this;
425  }
426 
428  ConstComponentIterator operator++(int) noexcept // postfix
429  {
430  return ConstComponentIterator{ this->Array, this->NumComps, this->TupleId,
431  this->ComponentId++ };
432  }
433 
435  ConstComponentIterator& operator--() noexcept // prefix
436  {
437  --this->ComponentId;
438  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
439  "Const component iterator at invalid component id.");
440  return *this;
441  }
442 
444  ConstComponentIterator operator--(int) noexcept // postfix
445  {
446  return ConstComponentIterator{ this->Array, this->NumComps, this->TupleId,
447  this->ComponentId-- };
448  }
449 
452  {
453  return reference{ this->Array, this->NumComps, this->TupleId, this->ComponentId + i };
454  }
455 
457  reference operator*() const noexcept
458  {
459  return reference{ this->Array, this->NumComps, this->TupleId, this->ComponentId };
460  }
461 
462 #define VTK_TMP_MAKE_OPERATOR(OP) \
463  friend VTK_ITER_INLINE bool operator OP( \
464  const ConstComponentIterator& lhs, const ConstComponentIterator& rhs) noexcept \
465  { \
466  VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Mismatched arrays in iterator comparison."); \
467  VTK_ITER_ASSERT(lhs.TupleId == rhs.TupleId, "Mismatched tuple ids in iterator comparison."); \
468  VTK_ITER_ASSUME(lhs.NumComps.value > 0); \
469  VTK_ITER_ASSUME(lhs.NumComps.value == rhs.NumComps.value); \
470  return lhs.ComponentId OP rhs.ComponentId; \
471  }
472 
479 
480 #undef VTK_TMP_MAKE_OPERATOR
481 
484  {
485  this->ComponentId += offset;
486  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
487  "Const component iterator at invalid component id.");
488  return *this;
489  }
490 
492  const ConstComponentIterator& it, difference_type offset) noexcept
493  {
494  return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId + offset };
495  }
496 
498  difference_type offset, const ConstComponentIterator& it) noexcept
499  {
500  return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId + offset };
501  }
502 
505  {
506  this->ComponentId -= offset;
507  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
508  "Const component iterator at invalid component id.");
509  return *this;
510  }
511 
513  const ConstComponentIterator& it, difference_type offset) noexcept
514  {
515  return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId - offset };
516  }
517 
519  const ConstComponentIterator& it1, const ConstComponentIterator& it2) noexcept
520  {
521  VTK_ITER_ASSERT(it1.Array == it2.Array, "Cannot do math with iterators from different arrays.");
522  VTK_ITER_ASSERT(it1.TupleId == it2.TupleId,
523  "Cannot do math with component iterators from different "
524  "tuples.");
525  return it1.ComponentId - it2.ComponentId;
526  }
527 
528  friend VTK_ITER_INLINE void swap(
530  {
531  // Different arrays may use different iterator implementations.
532  VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Cannot swap iterators from different arrays.");
533 
534  using std::swap;
535  swap(lhs.TupleId, rhs.TupleId);
536  swap(lhs.ComponentId, rhs.ComponentId);
537  }
538 
539 private:
540  mutable ArrayType* Array;
541  NumCompsType NumComps;
542  TupleIdType TupleId;
543  ComponentIdType ComponentId;
544 };
545 
546 //------------------------------------------------------------------------------
547 // Component iterator
548 template <typename ArrayType, ComponentIdType TupleSize>
550 {
551 private:
552  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
553  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
554 
556  using APIType = GetAPIType<ArrayType>;
557 
558 public:
559  using iterator_category = std::random_access_iterator_tag;
560  using value_type = APIType;
564 
566  ComponentIterator() noexcept = default;
567 
570  ArrayType* array, NumCompsType numComps, TupleIdType tupleId, ComponentIdType comp) noexcept
571  : Ref(array, numComps, tupleId, comp)
572  {
573  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
574  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
575  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
576  "Component iterator at invalid tuple id.");
578  comp >= 0 && comp <= numComps.value, "Component iterator at invalid component id.");
579  }
580 
582  ComponentIterator(const ComponentIterator& o) noexcept = default;
583 
586  {
587  this->Ref.CopyReference(o.Ref);
588  return *this;
589  }
590 
592  ComponentIterator& operator++() noexcept // prefix
593  {
594  ++this->Ref.ComponentId;
595  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
596  "Component iterator at invalid component id.");
597  return *this;
598  }
599 
601  ComponentIterator operator++(int) noexcept // postfix
602  {
603  return ComponentIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId,
604  this->Ref.ComponentId++ };
605  }
606 
608  ComponentIterator& operator--() noexcept // prefix
609  {
610  --this->Ref.ComponentId;
611  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
612  "Component iterator at invalid component id.");
613  return *this;
614  }
615 
617  ComponentIterator operator--(int) noexcept // postfix
618  {
619  return ComponentIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId,
620  this->Ref.ComponentId-- };
621  }
622 
625  {
626  return reference{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId,
627  this->Ref.ComponentId + i };
628  }
629 
631  reference operator*() const noexcept { return this->Ref; }
632 
634  const pointer& operator->() const noexcept { return this->Ref; }
635 
636 #define VTK_TMP_MAKE_OPERATOR(OP) \
637  friend VTK_ITER_INLINE bool operator OP( \
638  const ComponentIterator& lhs, const ComponentIterator& rhs) noexcept \
639  { \
640  VTK_ITER_ASSERT( \
641  lhs.GetArray() == rhs.GetArray(), "Mismatched arrays in iterator comparison."); \
642  VTK_ITER_ASSERT( \
643  lhs.GetTupleId() == rhs.GetTupleId(), "Mismatched tuple ids in iterator comparison."); \
644  VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \
645  VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \
646  return lhs.GetComponentId() OP rhs.GetComponentId(); \
647  }
648 
655 
656 #undef VTK_TMP_MAKE_OPERATOR
657 
660  {
661  this->Ref.ComponentId += offset;
662  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
663  "Component iterator at invalid component id.");
664  return *this;
665  }
666 
668  const ComponentIterator& it, difference_type offset) noexcept
669  {
670  return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(),
671  it.GetComponentId() + offset };
672  }
673 
675  difference_type offset, const ComponentIterator& it) noexcept
676  {
677  return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(),
678  it.GetComponentId() + offset };
679  }
680 
683  {
684  this->Ref.ComponentId -= offset;
685  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
686  "Component iterator at invalid component id.");
687  return *this;
688  }
689 
691  const ComponentIterator& it, difference_type offset) noexcept
692  {
693  return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(),
694  it.GetComponentId() - offset };
695  }
696 
698  const ComponentIterator& it1, const ComponentIterator& it2) noexcept
699  {
700  VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(),
701  "Cannot do math with component iterators from different "
702  "arrays.");
703  VTK_ITER_ASSERT(it1.GetTupleId() == it2.GetTupleId(),
704  "Cannot do math with component iterators from different "
705  "tuples.");
706  return it1.GetComponentId() - it2.GetComponentId();
707  }
708 
709  friend VTK_ITER_INLINE void swap(ComponentIterator& lhs, ComponentIterator& rhs) noexcept
710  {
711  // Different arrays may use different iterator implementations.
713  lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays.");
714 
715  using std::swap;
716  swap(lhs.GetTupleId(), rhs.GetTupleId());
717  swap(lhs.GetComponentId(), rhs.GetComponentId());
718  }
719 
720  friend struct ConstComponentIterator<ArrayType, TupleSize>;
721 
722 protected:
723  // Needed for access from friend functions. We could just store the array
724  // and ID here instead of the ref, but meh.
725  ArrayType* GetArray() const noexcept { return this->Ref.Array; }
726  TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; }
727  const TupleIdType& GetTupleId() const noexcept { return this->Ref.TupleId; }
728  ComponentIdType& GetComponentId() noexcept { return this->Ref.ComponentId; }
729  const ComponentIdType& GetComponentId() const noexcept { return this->Ref.ComponentId; }
730  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
731  const NumCompsType& GetNumComps() const noexcept { return this->Ref.NumComps; }
732 
734 };
735 
736 //------------------------------------------------------------------------------
737 // Const tuple reference
738 template <typename ArrayType, ComponentIdType TupleSize>
740 {
741 private:
742  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
743  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
744 
746  using APIType = GetAPIType<ArrayType>;
747 
748 public:
750  using value_type = APIType;
754 
757  : Array(nullptr)
758  , TupleId(0)
759  {
760  }
761 
763  ConstTupleReference(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
764  : Array(array)
765  , NumComps(numComps)
766  , TupleId(tupleId)
767  {
768  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
769  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
770  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
771  "Const tuple reference at invalid tuple id.");
772  }
773 
776  : Array{ o.Array }
777  , NumComps{ o.NumComps }
778  , TupleId{ o.TupleId }
779  {
780  }
781 
783  ConstTupleReference(const ConstTupleReference&) noexcept = default;
786 
787  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
789  ConstTupleReference* operator->() noexcept { return this; }
791  const ConstTupleReference* operator->() const noexcept { return this; }
792 
793  // Caller must ensure that there are size() elements in array.
795  void GetTuple(APIType* tuple) const noexcept
796  {
797  VTK_ITER_ASSUME(this->NumComps.value > 0);
798  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
800  acc.Get(this->TupleId, tuple);
801  }
802 
803  // skips some runtime checks when both sizes are fixed:
804  template <typename OArrayType, ComponentIdType OSize>
806  const TupleReference<OArrayType, OSize>& other) const noexcept
807  {
808  // Check that types are convertible:
809  using OAPIType = GetAPIType<OArrayType>;
810  static_assert(
811  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
812 
813  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
814  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
815 
816  return std::equal(this->cbegin(), this->cend(), other.cbegin());
817  }
818 
819  // Needs a runtime check:
820  template <typename OArrayType, ComponentIdType OSize>
822  const TupleReference<OArrayType, OSize>& other) const noexcept
823  {
824  // Check that types are convertible:
825  using OAPIType = GetAPIType<OArrayType>;
826  static_assert(
827  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
828 
830  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
831 
832  return std::equal(this->cbegin(), this->cend(), other.cbegin());
833  }
834 
835  // skips some runtime checks when both sizes are fixed:
836  template <typename OArrayType, ComponentIdType OSize>
838  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
839  {
840  // Check that types are convertible:
841  using OAPIType = GetAPIType<OArrayType>;
842  static_assert(
843  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
844 
845  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
846  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
847 
848  return std::equal(this->cbegin(), this->cend(), other.cbegin());
849  }
850 
851  // Needs a runtime check:
852  template <typename OArrayType, ComponentIdType OSize>
854  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
855  {
856  // Check that types are convertible:
857  using OAPIType = GetAPIType<OArrayType>;
858  static_assert(
859  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
860 
862  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
863 
864  return std::equal(this->cbegin(), this->cend(), other.cbegin());
865  }
866 
867  template <typename OArrayType, ComponentIdType OSize>
869  {
870  return !(*this == o);
871  }
872 
873  template <typename OArrayT, ComponentIdType OSize>
875  {
876  return !(*this == o);
877  }
878 
881  {
882  return const_reference{ this->Array, this->NumComps, this->TupleId, i };
883  }
884 
886  size_type size() const noexcept { return this->NumComps.value; }
887 
889  const_iterator begin() const noexcept { return this->NewConstIterator(0); }
891  const_iterator end() const noexcept { return this->NewConstIterator(this->NumComps.value); }
892 
894  const_iterator cbegin() const noexcept { return this->NewConstIterator(0); }
896  const_iterator cend() const noexcept { return this->NewConstIterator(this->NumComps.value); }
897 
898  friend struct ConstTupleIterator<ArrayType, TupleSize>;
899 
900 protected:
901  // Intentionally hidden:
903  ConstTupleReference& operator=(const ConstTupleReference&) noexcept = default;
904 
907  {
908  VTK_ITER_ASSUME(this->NumComps.value > 0);
909  return const_iterator{ this->Array, this->NumComps, this->TupleId, comp };
910  }
911 
913  void CopyReference(const ConstTupleReference& o) noexcept
914  {
915  // Must use same array, other array types may use different implementations.
916  VTK_ITER_ASSERT(this->Array == o.Array, "Cannot copy reference objects between arrays.");
917  this->NumComps = o.NumComps;
918  this->TupleId = o.TupleId;
919  }
920 
921  mutable ArrayType* Array;
924 };
925 
926 //------------------------------------------------------------------------------
927 // Tuple reference
928 template <typename ArrayType, ComponentIdType TupleSize>
930 {
931 private:
932  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
933  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
934 
936  using APIType = GetAPIType<ArrayType>;
937 
938 public:
940  using value_type = APIType;
945 
947  TupleReference() noexcept
948  : Array(nullptr)
949  , TupleId(0)
950  {
951  }
952 
954  TupleReference(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
955  : Array(array)
956  , NumComps(numComps)
957  , TupleId(tupleId)
958  {
959  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
960  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
961  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
962  "Tuple reference at invalid tuple id.");
963  }
964 
966  TupleReference(const TupleReference&) = default;
968  TupleReference(TupleReference&&) noexcept = default;
969 
970  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
972  TupleReference* operator->() noexcept { return this; }
974  const TupleReference* operator->() const noexcept { return this; }
975 
976  // Caller must ensure that there are size() elements in array.
978  void GetTuple(APIType* tuple) const noexcept
979  {
980  VTK_ITER_ASSUME(this->NumComps.value > 0);
981  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
983  acc.Get(this->TupleId, tuple);
984  }
985 
986  // Caller must ensure that there are size() elements in array.
988  void SetTuple(const APIType* tuple) noexcept
989  {
990  VTK_ITER_ASSUME(this->NumComps.value > 0);
991  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
993  acc.Set(this->TupleId, tuple);
994  }
995 
997  TupleReference& operator=(const TupleReference& other) noexcept
998  {
999  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
1000  return *this;
1001  }
1002 
1003  // skips some runtime checks when both sizes are fixed:
1004  template <typename OArrayType, ComponentIdType OSize>
1006  const TupleReference<OArrayType, OSize>& other) noexcept
1007  {
1008  // Check that types are convertible:
1009  using OAPIType = GetAPIType<OArrayType>;
1010  static_assert(
1011  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1012 
1013  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1014  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
1015 
1016  std::copy_n(other.cbegin(), OSize, this->begin());
1017  return *this;
1018  }
1019 
1020  // Needs a runtime check:
1021  template <typename OArrayType, ComponentIdType OSize>
1023  const TupleReference<OArrayType, OSize>& other) noexcept
1024  {
1025  // Check that types are convertible:
1026  using OAPIType = GetAPIType<OArrayType>;
1027  static_assert(
1028  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1029 
1031  other.size() == this->NumComps.value, "Cannot assign tuples with different sizes.");
1032 
1033  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
1034  return *this;
1035  }
1036 
1037  // skips some runtime checks when both sizes are fixed:
1038  template <typename OArrayType, ComponentIdType OSize>
1040  const ConstTupleReference<OArrayType, OSize>& other) noexcept
1041  {
1042  // Check that types are convertible:
1043  using OAPIType = GetAPIType<OArrayType>;
1044  static_assert(
1045  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1046 
1047  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1048  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
1049 
1050  std::copy_n(other.cbegin(), OSize, this->begin());
1051  return *this;
1052  }
1053 
1054  // Needs a runtime check:
1055  template <typename OArrayType, ComponentIdType OSize>
1057  const ConstTupleReference<OArrayType, OSize>& other) noexcept
1058  {
1059  // Check that types are convertible:
1060  using OAPIType = GetAPIType<OArrayType>;
1061  static_assert(
1062  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1063 
1065  other.size() == this->NumComps.value, "Cannot assign tuples with different sizes.");
1066 
1067  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
1068  return *this;
1069  }
1070 
1071  // skips some runtime checks when both sizes are fixed:
1072  template <typename OArrayType, ComponentIdType OSize>
1074  const TupleReference<OArrayType, OSize>& other) const noexcept
1075  {
1076  // Check that types are convertible:
1077  using OAPIType = GetAPIType<OArrayType>;
1078  static_assert(
1079  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1080 
1081  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1082  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
1083 
1084  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1085  }
1086 
1087  // Needs a runtime check:
1088  template <typename OArrayType, ComponentIdType OSize>
1090  const TupleReference<OArrayType, OSize>& other) const noexcept
1091  {
1092  // Check that types are convertible:
1093  using OAPIType = GetAPIType<OArrayType>;
1094  static_assert(
1095  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1096 
1098  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
1099 
1100  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1101  }
1102 
1103  // skips some runtime checks when both sizes are fixed:
1104  template <typename OArrayType, ComponentIdType OSize>
1106  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
1107  {
1108  // Check that types are convertible:
1109  using OAPIType = GetAPIType<OArrayType>;
1110  static_assert(
1111  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1112 
1113  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1114  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
1115 
1116  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1117  }
1118 
1119  // Needs a runtime check:
1120  template <typename OArrayType, ComponentIdType OSize>
1122  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
1123  {
1124  // Check that types are convertible:
1125  using OAPIType = GetAPIType<OArrayType>;
1126  static_assert(
1127  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1128 
1130  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
1131 
1132  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1133  }
1134 
1135  template <typename OArrayType, ComponentIdType OSize>
1137  {
1138  return !(*this == o);
1139  }
1140 
1141  template <typename OArray, ComponentIdType OSize>
1143  {
1144  return !(*this == o);
1145  }
1146 
1147  // skips some runtime checks:
1148  template <typename OArrayType, ComponentIdType OSize>
1150  TupleReference<OArrayType, OSize> other) noexcept
1151  {
1152  // Check that types are convertible:
1153  using OAPIType = GetAPIType<OArrayType>;
1154  static_assert(
1155  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
1156 
1157  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1158  static_assert(TupleSize == OSize, "Cannot swap tuples with different sizes.");
1159 
1160  std::swap_ranges(this->begin(), this->end(), other.begin());
1161  }
1162 
1163  // Needs a runtime check:
1164  template <typename OArrayType, ComponentIdType OSize>
1166  TupleReference<OArrayType, OSize> other) noexcept
1167  {
1168  // Check that types are convertible:
1169  using OAPIType = GetAPIType<OArrayType>;
1170  static_assert(
1171  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
1172 
1174  other.size() == this->NumComps.value, "Cannot swap tuples with different sizes.");
1175 
1176  std::swap_ranges(this->begin(), this->end(), other.begin());
1177  }
1178 
1179  friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept { a.swap(b); }
1180 
1181  template <typename OArray, ComponentIdType OSize>
1183  {
1184  a.swap(b);
1185  }
1186 
1189  {
1190  return reference{ this->Array, this->NumComps, this->TupleId, i };
1191  }
1192 
1195  {
1196  // Let the reference type do the lookup during implicit conversion.
1197  return const_reference{ this->Array, this->NumComps, this->TupleId, i };
1198  }
1199 
1201  void fill(const value_type& v) noexcept { std::fill(this->begin(), this->end(), v); }
1202 
1204  size_type size() const noexcept { return this->NumComps.value; }
1205 
1207  iterator begin() noexcept { return this->NewIterator(0); }
1209  iterator end() noexcept { return this->NewIterator(this->NumComps.value); }
1210 
1212  const_iterator begin() const noexcept { return this->NewConstIterator(0); }
1214  const_iterator end() const noexcept { return this->NewConstIterator(this->NumComps.value); }
1215 
1217  const_iterator cbegin() const noexcept { return this->NewConstIterator(0); }
1219  const_iterator cend() const noexcept { return this->NewConstIterator(this->NumComps.value); }
1220 
1221  friend struct ConstTupleReference<ArrayType, TupleSize>;
1222  friend struct TupleIterator<ArrayType, TupleSize>;
1223 
1224 protected:
1226  iterator NewIterator(ComponentIdType comp) const noexcept
1227  {
1228  VTK_ITER_ASSUME(this->NumComps.value > 0);
1229  return iterator{ this->Array, this->NumComps, this->TupleId, comp };
1230  }
1231 
1234  {
1235  VTK_ITER_ASSUME(this->NumComps.value > 0);
1236  return const_iterator{ this->Array, this->NumComps, this->TupleId, comp };
1237  }
1238 
1240  void CopyReference(const TupleReference& o) noexcept
1241  {
1242  // Must use same array, other array types may use different implementations.
1243  VTK_ITER_ASSERT(this->Array == o.Array, "Cannot copy reference objects between arrays.");
1244  this->NumComps = o.NumComps;
1245  this->TupleId = o.TupleId;
1246  }
1247 
1248  mutable ArrayType* Array;
1251 };
1252 
1253 //------------------------------------------------------------------------------
1254 // Const tuple iterator
1255 template <typename ArrayType, ComponentIdType TupleSize>
1257 {
1258 private:
1259  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
1260  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
1261 
1263 
1264 public:
1265  using iterator_category = std::random_access_iterator_tag;
1270 
1272  ConstTupleIterator() noexcept = default;
1273 
1275  ConstTupleIterator(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
1276  : Ref(array, numComps, tupleId)
1277  {
1278  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
1279  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
1280  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
1281  "Const tuple iterator at invalid tuple id.");
1282  }
1283 
1286  : Ref{ o.Ref }
1287  {
1288  }
1289 
1291  ConstTupleIterator(const ConstTupleIterator& o) noexcept = default;
1294  {
1295  this->Ref.CopyReference(o.Ref);
1296  return *this;
1297  }
1298 
1300  ConstTupleIterator& operator++() noexcept // prefix
1301  {
1302  ++this->Ref.TupleId;
1304  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1305  "Const tuple iterator at invalid component id.");
1306  return *this;
1307  }
1308 
1310  ConstTupleIterator operator++(int) noexcept // postfix
1311  {
1312  return ConstTupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId++ };
1313  }
1314 
1316  ConstTupleIterator& operator--() noexcept // prefix
1317  {
1318  --this->Ref.TupleId;
1320  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1321  "Const tuple iterator at invalid component id.");
1322  return *this;
1323  }
1324 
1326  ConstTupleIterator operator--(int) noexcept // postfix
1327  {
1328  return ConstTupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId-- };
1329  }
1330 
1333  {
1334  return reference{ this->GetArray(), this->GetNumComps(), this->GetTupleId() + i };
1335  }
1336 
1338  reference operator*() noexcept { return this->Ref; }
1339 
1341  pointer operator->() noexcept { return this->Ref; }
1342 
1343 #define VTK_TMP_MAKE_OPERATOR(OP) \
1344  friend VTK_ITER_INLINE bool operator OP( \
1345  const ConstTupleIterator& lhs, const ConstTupleIterator& rhs) noexcept \
1346  { \
1347  VTK_ITER_ASSERT( \
1348  lhs.GetArray() == rhs.GetArray(), "Cannot compare iterators from different arrays."); \
1349  VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \
1350  VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \
1351  return lhs.GetTupleId() OP rhs.GetTupleId(); \
1352  }
1353 
1360 
1361 #undef VTK_TMP_MAKE_OPERATOR
1362 
1365  {
1366  this->Ref.TupleId += offset;
1368  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1369  "Const tuple iterator at invalid component id.");
1370  return *this;
1371  }
1372 
1374  const ConstTupleIterator& it, difference_type offset) noexcept
1375  {
1376  return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1377  }
1378 
1380  difference_type offset, const ConstTupleIterator& it) noexcept
1381  {
1382  return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1383  }
1384 
1387  {
1388  this->Ref.TupleId -= offset;
1390  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1391  "Const tuple iterator at invalid component id.");
1392  return *this;
1393  }
1394 
1396  const ConstTupleIterator& it, difference_type offset) noexcept
1397  {
1398  return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() - offset };
1399  }
1400 
1402  const ConstTupleIterator& it1, const ConstTupleIterator& it2) noexcept
1403  {
1404  VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(),
1405  "Cannot do math with tuple iterators from different "
1406  "arrays.");
1407  return it1.GetTupleId() - it2.GetTupleId();
1408  }
1409 
1411  {
1412  // Different arrays may use different iterator implementations.
1414  lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays.");
1415 
1416  using std::swap;
1417  swap(lhs.GetTupleId(), rhs.GetTupleId());
1418  }
1419 
1420 private:
1422  ArrayType* GetArray() const noexcept { return this->Ref.Array; }
1424  ArrayType*& GetArray() noexcept { return this->Ref.Array; }
1426  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
1428  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
1430  TupleIdType GetTupleId() const noexcept { return this->Ref.TupleId; }
1432  TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; }
1433 
1434  ConstTupleReference<ArrayType, TupleSize> Ref;
1435 };
1436 
1437 //------------------------------------------------------------------------------
1438 // Tuple iterator
1439 template <typename ArrayType, ComponentIdType TupleSize>
1441 {
1442 private:
1443  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
1444  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
1445 
1447 
1448 public:
1449  using iterator_category = std::random_access_iterator_tag;
1454 
1456  TupleIterator() noexcept = default;
1457 
1459  TupleIterator(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
1460  : Ref(array, numComps, tupleId)
1461  {
1462  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
1463  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
1465  tupleId >= 0 && tupleId <= array->GetNumberOfTuples(), "Tuple iterator at invalid tuple id.");
1466  }
1467 
1469  TupleIterator(const TupleIterator& o) noexcept = default;
1470 
1473  {
1474  this->Ref.CopyReference(o.Ref);
1475  return *this;
1476  }
1477 
1479  TupleIterator& operator++() noexcept // prefix
1480  {
1481  ++this->Ref.TupleId;
1483  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1484  "Tuple iterator at invalid component id.");
1485  return *this;
1486  }
1487 
1489  TupleIterator operator++(int) noexcept // postfix
1490  {
1491  return TupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId++ };
1492  }
1493 
1495  TupleIterator& operator--() noexcept // prefix
1496  {
1497  --this->Ref.TupleId;
1499  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1500  "Tuple iterator at invalid component id.");
1501  return *this;
1502  }
1503 
1505  TupleIterator operator--(int) noexcept // postfix
1506  {
1507  return TupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId-- };
1508  }
1509 
1512  {
1513  return reference{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId + i };
1514  }
1515 
1517  reference operator*() noexcept { return this->Ref; }
1518 
1520  pointer& operator->() noexcept { return this->Ref; }
1521 
1522 #define VTK_TMP_MAKE_OPERATOR(OP) \
1523  friend VTK_ITER_INLINE bool operator OP( \
1524  const TupleIterator& lhs, const TupleIterator& rhs) noexcept \
1525  { \
1526  VTK_ITER_ASSERT( \
1527  lhs.GetArray() == rhs.GetArray(), "Cannot compare iterators from different arrays."); \
1528  VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \
1529  VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \
1530  return lhs.GetTupleId() OP rhs.GetTupleId(); \
1531  }
1532 
1539 
1540 #undef VTK_TMP_MAKE_OPERATOR
1541 
1544  {
1545  this->Ref.TupleId += offset;
1547  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1548  "Tuple iterator at invalid component id.");
1549  return *this;
1550  }
1551 
1553  const TupleIterator& it, difference_type offset) noexcept
1554  {
1555  return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1556  }
1557 
1559  difference_type offset, const TupleIterator& it) noexcept
1560  {
1561  return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1562  }
1563 
1566  {
1567  this->Ref.TupleId -= offset;
1569  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1570  "Tuple iterator at invalid component id.");
1571  return *this;
1572  }
1573 
1575  const TupleIterator& it, difference_type offset) noexcept
1576  {
1577  return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() - offset };
1578  }
1579 
1581  const TupleIterator& it1, const TupleIterator& it2) noexcept
1582  {
1583  VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(),
1584  "Cannot do math with tuple iterators from different "
1585  "arrays.");
1586  return it1.GetTupleId() - it2.GetTupleId();
1587  }
1588 
1589  friend VTK_ITER_INLINE void swap(TupleIterator& lhs, TupleIterator& rhs) noexcept
1590  {
1591  // Different arrays may use different iterator implementations.
1593  lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays.");
1594 
1595  using std::swap;
1596  swap(lhs.GetTupleId(), rhs.GetTupleId());
1597  }
1598 
1599  friend struct ConstTupleIterator<ArrayType, TupleSize>;
1600  friend struct ConstTupleReference<ArrayType, TupleSize>;
1601 
1602 protected:
1604  ArrayType* GetArray() const noexcept { return this->Ref.Array; }
1606  ArrayType*& GetArray() noexcept { return this->Ref.Array; }
1608  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
1610  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
1612  TupleIdType GetTupleId() const noexcept { return this->Ref.TupleId; }
1614  TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; }
1615 
1617 };
1618 
1619 //------------------------------------------------------------------------------
1620 // Tuple range
1621 template <typename ArrayTypeT, ComponentIdType TupleSize>
1623 {
1624 private:
1626  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
1627  static_assert(IsVtkDataArray<ArrayTypeT>::value, "Invalid array type.");
1628 
1629 public:
1630  using ArrayType = ArrayTypeT;
1641 
1642  // May be DynamicTupleSize, or the actual tuple size.
1643  constexpr static ComponentIdType TupleSizeTag = TupleSize;
1644 
1650 
1652  TupleRange() noexcept = default;
1653 
1655  TupleRange(ArrayType* arr, TupleIdType beginTuple, TupleIdType endTuple) noexcept
1656  : Array(arr)
1657  , NumComps(arr)
1658  , BeginTuple(beginTuple)
1659  , EndTuple(endTuple)
1660  {
1661  assert(this->Array);
1662  assert(beginTuple >= 0 && beginTuple <= endTuple);
1663  assert(endTuple >= 0 && endTuple <= this->Array->GetNumberOfTuples());
1664  }
1665 
1667  TupleRange GetSubRange(TupleIdType beginTuple = 0, TupleIdType endTuple = -1) const noexcept
1668  {
1669  const TupleIdType realBegin = this->BeginTuple + beginTuple;
1670  const TupleIdType realEnd = endTuple >= 0 ? this->BeginTuple + endTuple : this->EndTuple;
1671 
1672  return TupleRange{ this->Array, realBegin, realEnd };
1673  }
1674 
1676  ArrayType* GetArray() const noexcept { return this->Array; }
1678  ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
1680  TupleIdType GetBeginTupleId() const noexcept { return this->BeginTuple; }
1682  TupleIdType GetEndTupleId() const noexcept { return this->EndTuple; }
1683 
1685  size_type size() const noexcept { return this->EndTuple - this->BeginTuple; }
1686 
1688  iterator begin() noexcept { return this->NewIter(this->BeginTuple); }
1690  iterator end() noexcept { return this->NewIter(this->EndTuple); }
1691 
1693  const_iterator begin() const noexcept { return this->NewCIter(this->BeginTuple); }
1695  const_iterator end() const noexcept { return this->NewCIter(this->EndTuple); }
1696 
1698  const_iterator cbegin() const noexcept { return this->NewCIter(this->BeginTuple); }
1700  const_iterator cend() const noexcept { return this->NewCIter(this->EndTuple); }
1701 
1704  {
1705  return reference{ this->Array, this->NumComps, this->BeginTuple + i };
1706  }
1707 
1710  {
1711  return const_reference{ this->Array, this->NumComps, this->BeginTuple + i };
1712  }
1713 
1714 private:
1716  iterator NewIter(TupleIdType t) const { return iterator{ this->Array, this->NumComps, t }; }
1717 
1719  const_iterator NewCIter(TupleIdType t) const
1720  {
1721  return const_iterator{ this->Array, this->NumComps, t };
1722  }
1723 
1724  mutable ArrayType* Array{ nullptr };
1725  NumCompsType NumComps{};
1726  TupleIdType BeginTuple{ 0 };
1727  TupleIdType EndTuple{ 0 };
1728 };
1729 
1730 // Unimplemented, only used inside decltype in SelectTupleRange:
1731 template <typename ArrayType, ComponentIdType TupleSize>
1733 
1734 VTK_ABI_NAMESPACE_END
1735 } // end namespace detail
1736 } // end namespace vtk
1737 
1739 
1740 #endif // __VTK_WRAP__
1741 
1742 // VTK-HeaderTest-Exclude: vtkDataArrayTupleRange_Generic.h
abstract superclass for arrays of numeric data
Definition: vtkDataArray.h:54
@ value
Definition: vtkX3D.h:220
@ offset
Definition: vtkX3D.h:438
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
Efficient templated access to vtkDataArray.
ComponentReference< ArrayType, TupleSize > Ref
ComponentIdType & GetComponentId() noexcept
VTK_ITER_INLINE ComponentIterator(const ComponentIterator &o) noexcept=default
VTK_ITER_INLINE reference operator[](difference_type i) const noexcept
VTK_ITER_INLINE const pointer & operator->() const noexcept
friend VTK_ITER_INLINE difference_type operator-(const ComponentIterator &it1, const ComponentIterator &it2) noexcept
VTK_ITER_INLINE ComponentIterator operator++(int) noexcept
const ComponentIdType & GetComponentId() const noexcept
friend VTK_ITER_INLINE void swap(ComponentIterator &lhs, ComponentIterator &rhs) noexcept
VTK_ITER_INLINE ComponentIterator operator--(int) noexcept
std::random_access_iterator_tag iterator_category
VTK_ITER_INLINE ComponentIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE ComponentIterator & operator=(const ComponentIterator &o) noexcept
friend VTK_ITER_INLINE ComponentIterator operator+(const ComponentIterator &it, difference_type offset) noexcept
const NumCompsType & GetNumComps() const noexcept
VTK_ITER_INLINE ComponentIterator() noexcept=default
VTK_ITER_INLINE ComponentIterator & operator+=(difference_type offset) noexcept
VTK_ITER_INLINE ComponentIterator & operator++() noexcept
VTK_ITER_INLINE reference operator*() const noexcept
VTK_ITER_INLINE ComponentIterator & operator--() noexcept
friend VTK_ITER_INLINE ComponentIterator operator+(difference_type offset, const ComponentIterator &it) noexcept
friend VTK_ITER_INLINE ComponentIterator operator-(const ComponentIterator &it, difference_type offset) noexcept
const TupleIdType & GetTupleId() const noexcept
VTK_ITER_INLINE ComponentReference operator++() noexcept
VTK_ITER_INLINE ComponentReference(ComponentReference &&o) noexcept=default
VTK_ITER_INLINE ComponentReference operator=(ComponentReference &&o) noexcept
VTK_ITER_INLINE APIType operator++(int) noexcept
VTK_ITER_INLINE ComponentReference operator--() noexcept
friend VTK_ITER_INLINE void swap(ComponentReference lhs, ComponentReference rhs) noexcept
VTK_ITER_INLINE ComponentReference(const ComponentReference &o) noexcept=default
friend VTK_ITER_INLINE void swap(APIType &lhs, ComponentReference rhs) noexcept
VTK_ITER_INLINE ComponentReference operator=(APIType val) noexcept
friend VTK_ITER_INLINE void swap(ComponentReference lhs, ComponentReference< OArray, OSize > rhs) noexcept
VTK_ITER_INLINE ComponentReference(ArrayType *array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept
VTK_ITER_INLINE ComponentReference operator=(const ComponentReference< OArray, OSize > &o) noexcept
friend VTK_ITER_INLINE void swap(ComponentReference lhs, APIType &rhs) noexcept
VTK_ITER_INLINE ComponentReference operator=(const ComponentReference &o) noexcept
VTK_ITER_INLINE void CopyReference(const ComponentReference &o) noexcept
friend VTK_ITER_INLINE ConstComponentIterator operator+(difference_type offset, const ConstComponentIterator &it) noexcept
VTK_ITER_INLINE ConstComponentIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE ConstComponentIterator(const ConstComponentIterator &o) noexcept=default
friend VTK_ITER_INLINE difference_type operator-(const ConstComponentIterator &it1, const ConstComponentIterator &it2) noexcept
VTK_ITER_INLINE ConstComponentIterator & operator+=(difference_type offset) noexcept
std::random_access_iterator_tag iterator_category
VTK_ITER_INLINE reference operator*() const noexcept
VTK_ITER_INLINE ConstComponentIterator operator--(int) noexcept
VTK_ITER_INLINE ConstComponentIterator & operator++() noexcept
friend VTK_ITER_INLINE void swap(ConstComponentIterator &lhs, ConstComponentIterator &rhs) noexcept
VTK_ITER_INLINE ConstComponentIterator(const ComponentIterator< ArrayType, TupleSize > &o) noexcept
VTK_ITER_INLINE ConstComponentIterator & operator=(const ConstComponentIterator &o) noexcept=default
VTK_ITER_INLINE ConstComponentIterator & operator--() noexcept
friend VTK_ITER_INLINE ConstComponentIterator operator-(const ConstComponentIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE ConstComponentIterator(ArrayType *array, NumCompsType numComps, TupleIdType tupleId, ComponentIdType comp) noexcept
VTK_ITER_INLINE ConstComponentIterator operator++(int) noexcept
friend VTK_ITER_INLINE ConstComponentIterator operator+(const ConstComponentIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE reference operator[](difference_type i) const noexcept
VTK_ITER_INLINE ConstComponentReference(const ConstComponentReference &o) noexcept=default
VTK_ITER_INLINE ConstComponentReference(const ComponentReference< ArrayType, TupleSize > &o)
VTK_ITER_INLINE ConstComponentReference & operator=(const ConstComponentReference &o) noexcept
VTK_ITER_INLINE ConstComponentReference(ArrayType *array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept
VTK_ITER_INLINE ConstComponentReference(ConstComponentReference &&o) noexcept=default
VTK_ITER_INLINE ConstComponentReference & operator=(ConstComponentReference &&o) noexcept
friend VTK_ITER_INLINE void swap(ConstTupleIterator &lhs, ConstTupleIterator &rhs) noexcept
VTK_ITER_INLINE ConstTupleIterator operator--(int) noexcept
friend VTK_ITER_INLINE ConstTupleIterator operator+(difference_type offset, const ConstTupleIterator &it) noexcept
VTK_ITER_INLINE reference operator*() noexcept
VTK_ITER_INLINE ConstTupleIterator() noexcept=default
VTK_ITER_INLINE pointer operator->() noexcept
std::random_access_iterator_tag iterator_category
friend VTK_ITER_INLINE ConstTupleIterator operator+(const ConstTupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE reference operator[](difference_type i) noexcept
VTK_ITER_INLINE ConstTupleIterator & operator--() noexcept
VTK_ITER_INLINE ConstTupleIterator & operator-=(difference_type offset) noexcept
friend VTK_ITER_INLINE ConstTupleIterator operator-(const ConstTupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE ConstTupleIterator(const ConstTupleIterator &o) noexcept=default
VTK_ITER_INLINE ConstTupleIterator & operator+=(difference_type offset) noexcept
VTK_ITER_INLINE ConstTupleIterator(const TupleIterator< ArrayType, TupleSize > &o) noexcept
VTK_ITER_INLINE ConstTupleIterator & operator=(const ConstTupleIterator &o) noexcept
friend VTK_ITER_INLINE difference_type operator-(const ConstTupleIterator &it1, const ConstTupleIterator &it2) noexcept
VTK_ITER_INLINE ConstTupleIterator & operator++() noexcept
VTK_ITER_INLINE ConstTupleIterator operator++(int) noexcept
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE size_type size() const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE ConstTupleReference(ConstTupleReference &&) noexcept=default
VTK_ITER_INLINE const ConstTupleReference * operator->() const noexcept
VTK_ITER_INLINE const_iterator end() const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE const_iterator begin() const noexcept
VTK_ITER_INLINE void CopyReference(const ConstTupleReference &o) noexcept
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
VTK_ITER_INLINE ConstTupleReference(ArrayType *array, NumCompsType numComps, TupleIdType tupleId) noexcept
VTK_ITER_INLINE ConstTupleReference(const ConstTupleReference &) noexcept=default
VTK_ITER_INLINE void GetTuple(APIType *tuple) const noexcept
VTK_ITER_INLINE bool operator!=(const ConstTupleReference< OArrayT, OSize > &o) const noexcept
VTK_ITER_INLINE const_iterator NewConstIterator(ComponentIdType comp) const noexcept
VTK_ITER_INLINE ConstTupleReference & operator=(const ConstTupleReference &) noexcept=default
VTK_ITER_INLINE const_iterator cbegin() const noexcept
VTK_ITER_INLINE ConstTupleReference(const TupleReference< ArrayType, TupleSize > &o) noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
VTK_ITER_INLINE TupleIdType & GetTupleId() noexcept
friend VTK_ITER_INLINE TupleIterator operator+(const TupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE ArrayType *& GetArray() noexcept
friend VTK_ITER_INLINE void swap(TupleIterator &lhs, TupleIterator &rhs) noexcept
VTK_ITER_INLINE NumCompsType GetNumComps() const noexcept
VTK_ITER_INLINE TupleIterator(const TupleIterator &o) noexcept=default
VTK_ITER_INLINE TupleIterator & operator=(const TupleIterator &o) noexcept
friend VTK_ITER_INLINE TupleIterator operator-(const TupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE pointer & operator->() noexcept
VTK_ITER_INLINE TupleIdType GetTupleId() const noexcept
VTK_ITER_INLINE TupleIterator & operator--() noexcept
TupleReference< ArrayType, TupleSize > Ref
VTK_ITER_INLINE TupleIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE ArrayType * GetArray() const noexcept
VTK_ITER_INLINE reference operator[](difference_type i) noexcept
friend VTK_ITER_INLINE TupleIterator operator+(difference_type offset, const TupleIterator &it) noexcept
VTK_ITER_INLINE reference operator*() noexcept
VTK_ITER_INLINE NumCompsType & GetNumComps() noexcept
VTK_ITER_INLINE TupleIterator & operator++() noexcept
VTK_ITER_INLINE TupleIterator operator++(int) noexcept
VTK_ITER_INLINE TupleIterator operator--(int) noexcept
friend VTK_ITER_INLINE difference_type operator-(const TupleIterator &it1, const TupleIterator &it2) noexcept
std::random_access_iterator_tag iterator_category
VTK_ITER_INLINE TupleIterator() noexcept=default
VTK_ITER_INLINE TupleIterator & operator+=(difference_type offset) noexcept
VTK_ITER_INLINE const_iterator begin() const noexcept
VTK_ITER_INLINE TupleIdType GetBeginTupleId() const noexcept
VTK_ITER_INLINE TupleIdType GetEndTupleId() const noexcept
TupleIterator< ArrayType, TupleSize > TupleIteratorType
VTK_ITER_INLINE TupleRange() noexcept=default
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
VTK_ITER_INLINE const_iterator end() const noexcept
VTK_ITER_INLINE size_type size() const noexcept
ConstTupleIterator< ArrayType, TupleSize > ConstTupleIteratorType
VTK_ITER_INLINE reference operator[](size_type i) noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
TupleReference< ArrayType, TupleSize > TupleReferenceType
VTK_ITER_INLINE ComponentIdType GetTupleSize() const noexcept
constexpr static ComponentIdType TupleSizeTag
VTK_ITER_INLINE const_iterator cbegin() const noexcept
VTK_ITER_INLINE iterator end() noexcept
ConstTupleReference< ArrayType, TupleSize > ConstTupleReferenceType
VTK_ITER_INLINE TupleRange GetSubRange(TupleIdType beginTuple=0, TupleIdType endTuple=-1) const noexcept
VTK_ITER_INLINE ArrayType * GetArray() const noexcept
VTK_ITER_INLINE iterator begin() noexcept
VTK_ITER_INLINE TupleReference & operator=(const TupleReference &other) noexcept
VTK_ITER_INLINE void SetTuple(const APIType *tuple) noexcept
VTK_ITER_INLINE const_iterator begin() const noexcept
VTK_ITER_INLINE reference operator[](size_type i) noexcept
VTK_ITER_INLINE TupleReference(const TupleReference &)=default
VTK_ITER_INLINE void GetTuple(APIType *tuple) const noexcept
VTK_ITER_INLINE const_iterator cbegin() const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, void > swap(TupleReference< OArrayType, OSize > other) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE const TupleReference * operator->() const noexcept
friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept
VTK_ITER_INLINE TupleReference(ArrayType *array, NumCompsType numComps, TupleIdType tupleId) noexcept
VTK_ITER_INLINE TupleReference(TupleReference &&) noexcept=default
VTK_ITER_INLINE iterator NewIterator(ComponentIdType comp) const noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
VTK_ITER_INLINE size_type size() const noexcept
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
VTK_ITER_INLINE void CopyReference(const TupleReference &o) noexcept
VTK_ITER_INLINE iterator begin() noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, void > swap(TupleReference< OArrayType, OSize > other) noexcept
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE TupleReference() noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, TupleReference & > operator=(const TupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, TupleReference & > operator=(const ConstTupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE const_iterator end() const noexcept
VTK_ITER_INLINE iterator end() noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< 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 EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE void fill(const value_type &v) noexcept
VTK_ITER_INLINE const_iterator NewConstIterator(ComponentIdType comp) const noexcept
VTK_ITER_INLINE bool operator!=(const ConstTupleReference< OArray, OSize > &o) const noexcept
friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference< OArray, OSize > b) 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_ASSERT(x, msg)
#define VTK_ITER_ASSUME
#define VTK_TMP_MAKE_OPERATOR(OP)
#define VTK_REF_OP_OVERLOADS(Op, ImplOp)