VTK  9.2.6
vtkDataArrayTupleRange_Generic.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkDataArrayTupleRange_Generic.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 =========================================================================*/
20 #ifndef vtkDataArrayTupleRange_Generic_h
21 #define vtkDataArrayTupleRange_Generic_h
22 
23 #include "vtkAssume.h"
24 #include "vtkDataArrayAccessor.h"
25 #include "vtkDataArrayMeta.h"
26 
27 #include <algorithm>
28 #include <cassert>
29 #include <iterator>
30 #include <type_traits>
31 
33 
34 namespace vtk
35 {
36 
37 namespace detail
38 {
39 
40 // Forward decs for friends/args
41 template <typename ArrayType, ComponentIdType>
43 template <typename ArrayType, ComponentIdType>
45 template <typename ArrayType, ComponentIdType>
47 template <typename ArrayType, ComponentIdType>
49 template <typename ArrayType, ComponentIdType>
50 struct ConstTupleReference;
51 template <typename ArrayType, ComponentIdType>
52 struct TupleReference;
53 template <typename ArrayType, ComponentIdType>
54 struct ConstTupleIterator;
55 template <typename ArrayType, ComponentIdType>
56 struct TupleIterator;
57 template <typename ArrayType, ComponentIdType>
58 struct TupleRange;
59 
60 //------------------------------------------------------------------------------
61 // Const component reference
62 template <typename ArrayType, ComponentIdType TupleSize>
64 {
65 private:
66  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
67  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
68 
70  using APIType = GetAPIType<ArrayType>;
71 
72 public:
73  using value_type = APIType;
74 
77  : Array{ nullptr }
78  , NumComps{}
79  , TupleId{ 0 }
80  , ComponentId{ 0 }
81  {
82  }
83 
86  ArrayType* array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept
87  : Array{ array }
88  , NumComps{ numComps }
89  , TupleId{ tuple }
90  , ComponentId{ comp }
91  {
92  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
93  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
95  tuple >= 0 && tuple <= array->GetNumberOfTuples(), "Invalid tuple accessed by iterator.");
96  VTK_ITER_ASSERT(comp >= 0 && comp <= array->GetNumberOfComponents(),
97  "Invalid component accessed by iterator.");
98  }
99 
102  : Array{ o.Array }
103  , NumComps{ o.NumComps }
104  , TupleId{ o.TupleId }
105  , ComponentId{ o.ComponentId }
106  {
107  }
108 
110  ConstComponentReference(const ConstComponentReference& o) noexcept = default;
111 
113  ConstComponentReference(ConstComponentReference&& o) noexcept = default;
114 
116  ConstComponentReference& operator=(const ConstComponentReference& o) noexcept
117  {
118  VTK_ITER_ASSERT(!this->Array, "Const reference already initialized.");
119  // Initialize the reference.
120  this->Array = o.Array;
121  this->NumComps = o.NumComps;
122  this->TupleId = o.TupleId;
123  this->ComponentId = o.ComponentId;
124  }
125 
128  {
129  VTK_ITER_ASSERT(!this->Array, "Const reference already initialized.");
130  // Initialize the reference.
131  this->Array = std::move(o.Array);
132  this->NumComps = std::move(o.NumComps);
133  this->TupleId = std::move(o.TupleId);
134  this->ComponentId = std::move(o.ComponentId);
135  }
136 
138  operator APIType() const noexcept
139  {
140  VTK_ITER_ASSUME(this->NumComps.value > 0);
141  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
143  return acc.Get(this->TupleId, this->ComponentId);
144  }
145 
146 protected:
147  mutable ArrayType* Array;
151 };
152 
153 //------------------------------------------------------------------------------
154 // Component reference
155 template <typename ArrayType, ComponentIdType TupleSize>
156 struct ComponentReference
157 {
158 private:
159  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
160  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
161 
162  using NumCompsType = GenericTupleSize<TupleSize>;
163  using APIType = GetAPIType<ArrayType>;
164 
165 public:
166  using value_type = APIType;
167 
170  : Array{ nullptr }
171  , NumComps{}
172  , TupleId{ 0 }
173  , ComponentId{ 0 }
174  {
175  }
176 
179  ArrayType* array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept
180  : Array{ array }
181  , NumComps{ numComps }
182  , TupleId{ tuple }
183  , ComponentId{ comp }
184  {
185  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
186  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
188  tuple >= 0 && tuple <= array->GetNumberOfTuples(), "Invalid tuple accessed by iterator.");
189  VTK_ITER_ASSERT(comp >= 0 && comp <= array->GetNumberOfComponents(),
190  "Invalid component accessed by iterator.");
191  }
192 
194  ComponentReference(const ComponentReference& o) noexcept = default;
196  ComponentReference(ComponentReference&& o) noexcept = default;
197 
199  ComponentReference operator=(const ComponentReference& o) noexcept
200  {
201  if (this->Array)
202  { // Already initialized. Assign the value, not the reference
203  return *this = static_cast<APIType>(o);
204  }
205  else
206  { // Initialize the reference.
207  this->Array = o.Array;
208  this->NumComps = o.NumComps;
209  this->TupleId = o.TupleId;
210  this->ComponentId = o.ComponentId;
211 
212  return *this;
213  }
214  }
215 
218  {
219  if (this->Array)
220  { // Already initialized. Assign the value, not the reference
221  return *this = std::move(static_cast<APIType>(o));
222  }
223  else
224  { // Initialize the reference.
225  this->Array = std::move(o.Array);
226  this->NumComps = std::move(o.NumComps);
227  this->TupleId = std::move(o.TupleId);
228  this->ComponentId = std::move(o.ComponentId);
229 
230  return *this;
231  }
232  }
233 
234  template <typename OArray, ComponentIdType OSize>
236  { // Always copy the value for different reference types:
237  const APIType tmp = o;
238  return *this = std::move(tmp);
239  }
240 
242  operator APIType() const noexcept
243  {
244  VTK_ITER_ASSUME(this->NumComps.value > 0);
245  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
247  return acc.Get(this->TupleId, this->ComponentId);
248  }
249 
251  ComponentReference operator=(APIType val) noexcept
252  {
253  VTK_ITER_ASSUME(this->NumComps.value > 0);
254  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
256  acc.Set(this->TupleId, this->ComponentId, val);
257  return *this;
258  }
259 
261  { // Swap values, not references:
262  APIType tmp = std::move(static_cast<APIType>(lhs));
263  lhs = std::move(static_cast<APIType>(rhs));
264  rhs = std::move(tmp);
265  }
266 
267  template <typename OArray, ComponentIdType OSize>
268  friend VTK_ITER_INLINE void swap(
270  { // Swap values, not references:
271  using OAPIType = GetAPIType<OArray>;
272  static_assert(
273  std::is_same<APIType, OAPIType>::value, "Cannot swap components with different types.");
274 
275  APIType tmp = std::move(static_cast<APIType>(lhs));
276  lhs = std::move(static_cast<APIType>(rhs));
277  rhs = std::move(tmp);
278  }
279 
280  friend VTK_ITER_INLINE void swap(ComponentReference lhs, APIType& rhs) noexcept
281  {
282  APIType tmp = std::move(static_cast<APIType>(lhs));
283  lhs = std::move(rhs);
284  rhs = std::move(tmp);
285  }
286 
287  friend VTK_ITER_INLINE void swap(APIType& lhs, ComponentReference rhs) noexcept
288  {
289  APIType tmp = std::move(lhs);
290  lhs = std::move(static_cast<APIType>(rhs));
291  rhs = std::move(tmp);
292  }
293 
295  ComponentReference operator++() noexcept // prefix
296  {
297  const APIType newVal = *this + 1;
298  *this = newVal;
299  return *this;
300  }
301 
303  APIType operator++(int) noexcept // postfix
304  {
305  const APIType retVal = *this;
306  *this = *this + 1;
307  return retVal;
308  }
309 
311  ComponentReference operator--() noexcept // prefix
312  {
313  const APIType newVal = *this - 1;
314  *this = newVal;
315  return *this;
316  }
317 
319  APIType operator--(int) noexcept // postfix
320  {
321  const APIType retVal = *this;
322  *this = *this - 1;
323  return retVal;
324  }
325 
326 #define VTK_REF_OP_OVERLOADS(Op, ImplOp) \
327  friend VTK_ITER_INLINE ComponentReference operator Op( \
328  ComponentReference lhs, APIType val) noexcept \
329  { \
330  const APIType newVal = lhs ImplOp val; \
331  lhs = newVal; \
332  return lhs; \
333  } \
334  friend VTK_ITER_INLINE ComponentReference operator Op( \
335  ComponentReference lhs, ComponentReference val) noexcept \
336  { \
337  const APIType newVal = lhs ImplOp val; \
338  lhs = newVal; \
339  return lhs; \
340  } \
341  friend VTK_ITER_INLINE APIType& operator Op(APIType& lhs, ComponentReference val) noexcept \
342  { \
343  const APIType newVal = lhs ImplOp val; \
344  lhs = newVal; \
345  return lhs; \
346  }
347 
348  VTK_REF_OP_OVERLOADS(+=, +)
349  VTK_REF_OP_OVERLOADS(-=, -)
350  VTK_REF_OP_OVERLOADS(*=, *)
351  VTK_REF_OP_OVERLOADS(/=, /)
352 
353 #undef VTK_REF_OP_OVERLOADS
354 
355  friend struct ConstComponentReference<ArrayType, TupleSize>;
356  friend struct ComponentIterator<ArrayType, TupleSize>;
357 
358 protected:
360  void CopyReference(const ComponentReference& o) noexcept
361  {
362  this->Array = o.Array;
363  this->NumComps = o.NumComps;
364  this->TupleId = o.TupleId;
365  this->ComponentId = o.ComponentId;
366  }
367 
368  mutable ArrayType* Array;
372 };
373 
374 //------------------------------------------------------------------------------
375 // Const component iterator
376 template <typename ArrayType, ComponentIdType TupleSize>
378 {
379 private:
380  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
381  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
382 
383  using NumCompsType = GenericTupleSize<TupleSize>;
384 
385 public:
386  using iterator_category = std::random_access_iterator_tag;
389  using pointer = void;
391 
394  : Array{ nullptr }
395  , TupleId{ 0 }
396  , ComponentId{ 0 }
397  {
398  }
399 
402  ArrayType* array, NumCompsType numComps, TupleIdType tupleId, ComponentIdType comp) noexcept
403  : Array(array)
404  , NumComps(numComps)
405  , TupleId(tupleId)
406  , ComponentId(comp)
407  {
408  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
409  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
410  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
411  "Const component iterator at invalid tuple id.");
412  VTK_ITER_ASSERT(comp >= 0 && comp <= this->NumComps.value,
413  "Const component iterator at invalid component id.");
414  }
415 
418  : Array{ o.GetArray() }
419  , NumComps{ o.GetNumComps() }
420  , TupleId{ o.GetTupleId() }
421  , ComponentId{ o.GetComponentId() }
422  {
423  }
424 
426  ConstComponentIterator(const ConstComponentIterator& o) noexcept = default;
428  ConstComponentIterator& operator=(const ConstComponentIterator& o) noexcept = default;
429 
431  ConstComponentIterator& operator++() noexcept // prefix
432  {
433  ++this->ComponentId;
434  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
435  "Const component iterator at invalid component id.");
436  return *this;
437  }
438 
440  ConstComponentIterator operator++(int) noexcept // postfix
441  {
442  return ConstComponentIterator{ this->Array, this->NumComps, this->TupleId,
443  this->ComponentId++ };
444  }
445 
447  ConstComponentIterator& operator--() noexcept // prefix
448  {
449  --this->ComponentId;
450  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
451  "Const component iterator at invalid component id.");
452  return *this;
453  }
454 
456  ConstComponentIterator operator--(int) noexcept // postfix
457  {
458  return ConstComponentIterator{ this->Array, this->NumComps, this->TupleId,
459  this->ComponentId-- };
460  }
461 
464  {
465  return reference{ this->Array, this->NumComps, this->TupleId, this->ComponentId + i };
466  }
467 
469  reference operator*() const noexcept
470  {
471  return reference{ this->Array, this->NumComps, this->TupleId, this->ComponentId };
472  }
473 
474 #define VTK_TMP_MAKE_OPERATOR(OP) \
475  friend VTK_ITER_INLINE bool operator OP( \
476  const ConstComponentIterator& lhs, const ConstComponentIterator& rhs) noexcept \
477  { \
478  VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Mismatched arrays in iterator comparison."); \
479  VTK_ITER_ASSERT(lhs.TupleId == rhs.TupleId, "Mismatched tuple ids in iterator comparison."); \
480  VTK_ITER_ASSUME(lhs.NumComps.value > 0); \
481  VTK_ITER_ASSUME(lhs.NumComps.value == rhs.NumComps.value); \
482  return lhs.ComponentId OP rhs.ComponentId; \
483  }
484 
491 
492 #undef VTK_TMP_MAKE_OPERATOR
493 
496  {
497  this->ComponentId += offset;
498  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
499  "Const component iterator at invalid component id.");
500  return *this;
501  }
502 
504  const ConstComponentIterator& it, difference_type offset) noexcept
505  {
506  return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId + offset };
507  }
508 
510  difference_type offset, const ConstComponentIterator& it) noexcept
511  {
512  return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId + offset };
513  }
514 
517  {
518  this->ComponentId -= offset;
519  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
520  "Const component iterator at invalid component id.");
521  return *this;
522  }
523 
525  const ConstComponentIterator& it, difference_type offset) noexcept
526  {
527  return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId - offset };
528  }
529 
531  const ConstComponentIterator& it1, const ConstComponentIterator& it2) noexcept
532  {
533  VTK_ITER_ASSERT(it1.Array == it2.Array, "Cannot do math with iterators from different arrays.");
534  VTK_ITER_ASSERT(it1.TupleId == it2.TupleId,
535  "Cannot do math with component iterators from different "
536  "tuples.");
537  return it1.ComponentId - it2.ComponentId;
538  }
539 
540  friend VTK_ITER_INLINE void swap(
542  {
543  // Different arrays may use different iterator implementations.
544  VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Cannot swap iterators from different arrays.");
545 
546  using std::swap;
547  swap(lhs.TupleId, rhs.TupleId);
548  swap(lhs.ComponentId, rhs.ComponentId);
549  }
550 
551 private:
552  mutable ArrayType* Array;
553  NumCompsType NumComps;
554  TupleIdType TupleId;
555  ComponentIdType ComponentId;
556 };
557 
558 //------------------------------------------------------------------------------
559 // Component iterator
560 template <typename ArrayType, ComponentIdType TupleSize>
561 struct ComponentIterator
562 {
563 private:
564  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
565  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
566 
567  using NumCompsType = GenericTupleSize<TupleSize>;
568  using APIType = GetAPIType<ArrayType>;
569 
570 public:
571  using iterator_category = std::random_access_iterator_tag;
572  using value_type = APIType;
576 
578  ComponentIterator() noexcept = default;
579 
582  ArrayType* array, NumCompsType numComps, TupleIdType tupleId, ComponentIdType comp) noexcept
583  : Ref(array, numComps, tupleId, comp)
584  {
585  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
586  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
587  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
588  "Component iterator at invalid tuple id.");
590  comp >= 0 && comp <= numComps.value, "Component iterator at invalid component id.");
591  }
592 
594  ComponentIterator(const ComponentIterator& o) noexcept = default;
595 
598  {
599  this->Ref.CopyReference(o.Ref);
600  return *this;
601  }
602 
604  ComponentIterator& operator++() noexcept // prefix
605  {
606  ++this->Ref.ComponentId;
607  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
608  "Component iterator at invalid component id.");
609  return *this;
610  }
611 
613  ComponentIterator operator++(int) noexcept // postfix
614  {
615  return ComponentIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId,
616  this->Ref.ComponentId++ };
617  }
618 
620  ComponentIterator& operator--() noexcept // prefix
621  {
622  --this->Ref.ComponentId;
623  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
624  "Component iterator at invalid component id.");
625  return *this;
626  }
627 
629  ComponentIterator operator--(int) noexcept // postfix
630  {
631  return ComponentIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId,
632  this->Ref.ComponentId-- };
633  }
634 
637  {
638  return reference{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId,
639  this->Ref.ComponentId + i };
640  }
641 
643  reference operator*() const noexcept { return this->Ref; }
644 
646  const pointer& operator->() const noexcept { return this->Ref; }
647 
648 #define VTK_TMP_MAKE_OPERATOR(OP) \
649  friend VTK_ITER_INLINE bool operator OP( \
650  const ComponentIterator& lhs, const ComponentIterator& rhs) noexcept \
651  { \
652  VTK_ITER_ASSERT( \
653  lhs.GetArray() == rhs.GetArray(), "Mismatched arrays in iterator comparison."); \
654  VTK_ITER_ASSERT( \
655  lhs.GetTupleId() == rhs.GetTupleId(), "Mismatched tuple ids in iterator comparison."); \
656  VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \
657  VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \
658  return lhs.GetComponentId() OP rhs.GetComponentId(); \
659  }
660 
667 
668 #undef VTK_TMP_MAKE_OPERATOR
669 
672  {
673  this->Ref.ComponentId += offset;
674  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
675  "Component iterator at invalid component id.");
676  return *this;
677  }
678 
680  const ComponentIterator& it, difference_type offset) noexcept
681  {
682  return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(),
683  it.GetComponentId() + offset };
684  }
685 
687  difference_type offset, const ComponentIterator& it) noexcept
688  {
689  return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(),
690  it.GetComponentId() + offset };
691  }
692 
695  {
696  this->Ref.ComponentId -= offset;
697  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
698  "Component iterator at invalid component id.");
699  return *this;
700  }
701 
703  const ComponentIterator& it, difference_type offset) noexcept
704  {
705  return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(),
706  it.GetComponentId() - offset };
707  }
708 
710  const ComponentIterator& it1, const ComponentIterator& it2) noexcept
711  {
712  VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(),
713  "Cannot do math with component iterators from different "
714  "arrays.");
715  VTK_ITER_ASSERT(it1.GetTupleId() == it2.GetTupleId(),
716  "Cannot do math with component iterators from different "
717  "tuples.");
718  return it1.GetComponentId() - it2.GetComponentId();
719  }
720 
721  friend VTK_ITER_INLINE void swap(ComponentIterator& lhs, ComponentIterator& rhs) noexcept
722  {
723  // Different arrays may use different iterator implementations.
725  lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays.");
726 
727  using std::swap;
728  swap(lhs.GetTupleId(), rhs.GetTupleId());
729  swap(lhs.GetComponentId(), rhs.GetComponentId());
730  }
731 
732  friend struct ConstComponentIterator<ArrayType, TupleSize>;
733 
734 protected:
735  // Needed for access from friend functions. We could just store the array
736  // and ID here instead of the ref, but meh.
737  ArrayType* GetArray() const noexcept { return this->Ref.Array; }
738  TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; }
739  const TupleIdType& GetTupleId() const noexcept { return this->Ref.TupleId; }
740  ComponentIdType& GetComponentId() noexcept { return this->Ref.ComponentId; }
741  const ComponentIdType& GetComponentId() const noexcept { return this->Ref.ComponentId; }
742  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
743  const NumCompsType& GetNumComps() const noexcept { return this->Ref.NumComps; }
744 
746 };
747 
748 //------------------------------------------------------------------------------
749 // Const tuple reference
750 template <typename ArrayType, ComponentIdType TupleSize>
751 struct ConstTupleReference
752 {
753 private:
754  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
755  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
756 
757  using NumCompsType = GenericTupleSize<TupleSize>;
758  using APIType = GetAPIType<ArrayType>;
759 
760 public:
762  using value_type = APIType;
766 
769  : Array(nullptr)
770  , TupleId(0)
771  {
772  }
773 
775  ConstTupleReference(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
776  : Array(array)
777  , NumComps(numComps)
778  , TupleId(tupleId)
779  {
780  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
781  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
782  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
783  "Const tuple reference at invalid tuple id.");
784  }
785 
788  : Array{ o.Array }
789  , NumComps{ o.NumComps }
790  , TupleId{ o.TupleId }
791  {
792  }
793 
795  ConstTupleReference(const ConstTupleReference&) noexcept = default;
797  ConstTupleReference(ConstTupleReference&&) noexcept = default;
798 
799  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
801  ConstTupleReference* operator->() noexcept { return this; }
803  const ConstTupleReference* operator->() const noexcept { return this; }
804 
805  // Caller must ensure that there are size() elements in array.
807  void GetTuple(APIType* tuple) const noexcept
808  {
809  VTK_ITER_ASSUME(this->NumComps.value > 0);
810  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
812  acc.Get(this->TupleId, tuple);
813  }
814 
815  // skips some runtime checks when both sizes are fixed:
816  template <typename OArrayType, ComponentIdType OSize>
818  const TupleReference<OArrayType, OSize>& other) const noexcept
819  {
820  // Check that types are convertible:
821  using OAPIType = GetAPIType<OArrayType>;
822  static_assert(
823  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
824 
825  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
826  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
827 
828  return std::equal(this->cbegin(), this->cend(), other.cbegin());
829  }
830 
831  // Needs a runtime check:
832  template <typename OArrayType, ComponentIdType OSize>
834  const TupleReference<OArrayType, OSize>& other) const noexcept
835  {
836  // Check that types are convertible:
837  using OAPIType = GetAPIType<OArrayType>;
838  static_assert(
839  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
840 
842  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
843 
844  return std::equal(this->cbegin(), this->cend(), other.cbegin());
845  }
846 
847  // skips some runtime checks when both sizes are fixed:
848  template <typename OArrayType, ComponentIdType OSize>
850  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
851  {
852  // Check that types are convertible:
853  using OAPIType = GetAPIType<OArrayType>;
854  static_assert(
855  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
856 
857  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
858  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
859 
860  return std::equal(this->cbegin(), this->cend(), other.cbegin());
861  }
862 
863  // Needs a runtime check:
864  template <typename OArrayType, ComponentIdType OSize>
866  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
867  {
868  // Check that types are convertible:
869  using OAPIType = GetAPIType<OArrayType>;
870  static_assert(
871  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
872 
874  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
875 
876  return std::equal(this->cbegin(), this->cend(), other.cbegin());
877  }
878 
879  template <typename OArrayType, ComponentIdType OSize>
881  {
882  return !(*this == o);
883  }
884 
885  template <typename OArrayT, ComponentIdType OSize>
887  {
888  return !(*this == o);
889  }
890 
893  {
894  return const_reference{ this->Array, this->NumComps, this->TupleId, i };
895  }
896 
898  size_type size() const noexcept { return this->NumComps.value; }
899 
901  const_iterator begin() const noexcept { return this->NewConstIterator(0); }
903  const_iterator end() const noexcept { return this->NewConstIterator(this->NumComps.value); }
904 
906  const_iterator cbegin() const noexcept { return this->NewConstIterator(0); }
908  const_iterator cend() const noexcept { return this->NewConstIterator(this->NumComps.value); }
909 
910  friend struct ConstTupleIterator<ArrayType, TupleSize>;
911 
912 protected:
913  // Intentionally hidden:
915  ConstTupleReference& operator=(const ConstTupleReference&) noexcept = default;
916 
919  {
920  VTK_ITER_ASSUME(this->NumComps.value > 0);
921  return const_iterator{ this->Array, this->NumComps, this->TupleId, comp };
922  }
923 
925  void CopyReference(const ConstTupleReference& o) noexcept
926  {
927  // Must use same array, other array types may use different implementations.
928  VTK_ITER_ASSERT(this->Array == o.Array, "Cannot copy reference objects between arrays.");
929  this->NumComps = o.NumComps;
930  this->TupleId = o.TupleId;
931  }
932 
933  mutable ArrayType* Array;
936 };
937 
938 //------------------------------------------------------------------------------
939 // Tuple reference
940 template <typename ArrayType, ComponentIdType TupleSize>
941 struct TupleReference
942 {
943 private:
944  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
945  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
946 
947  using NumCompsType = GenericTupleSize<TupleSize>;
948  using APIType = GetAPIType<ArrayType>;
949 
950 public:
952  using value_type = APIType;
957 
959  TupleReference() noexcept
960  : Array(nullptr)
961  , TupleId(0)
962  {
963  }
964 
966  TupleReference(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
967  : Array(array)
968  , NumComps(numComps)
969  , TupleId(tupleId)
970  {
971  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
972  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
973  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
974  "Tuple reference at invalid tuple id.");
975  }
976 
978  TupleReference(const TupleReference&) = default;
980  TupleReference(TupleReference&&) = default;
981 
982  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
984  TupleReference* operator->() noexcept { return this; }
986  const TupleReference* operator->() const noexcept { return this; }
987 
988  // Caller must ensure that there are size() elements in array.
990  void GetTuple(APIType* tuple) const noexcept
991  {
992  VTK_ITER_ASSUME(this->NumComps.value > 0);
993  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
995  acc.Get(this->TupleId, tuple);
996  }
997 
998  // Caller must ensure that there are size() elements in array.
1000  void SetTuple(const APIType* tuple) noexcept
1001  {
1002  VTK_ITER_ASSUME(this->NumComps.value > 0);
1003  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
1005  acc.Set(this->TupleId, tuple);
1006  }
1007 
1009  TupleReference& operator=(const TupleReference& other) noexcept
1010  {
1011  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
1012  return *this;
1013  }
1014 
1015  // skips some runtime checks when both sizes are fixed:
1016  template <typename OArrayType, ComponentIdType OSize>
1018  const TupleReference<OArrayType, OSize>& other) noexcept
1019  {
1020  // Check that types are convertible:
1021  using OAPIType = GetAPIType<OArrayType>;
1022  static_assert(
1023  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1024 
1025  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1026  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
1027 
1028  std::copy_n(other.cbegin(), OSize, this->begin());
1029  return *this;
1030  }
1031 
1032  // Needs a runtime check:
1033  template <typename OArrayType, ComponentIdType OSize>
1035  const TupleReference<OArrayType, OSize>& other) noexcept
1036  {
1037  // Check that types are convertible:
1038  using OAPIType = GetAPIType<OArrayType>;
1039  static_assert(
1040  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1041 
1043  other.size() == this->NumComps.value, "Cannot assign tuples with different sizes.");
1044 
1045  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
1046  return *this;
1047  }
1048 
1049  // skips some runtime checks when both sizes are fixed:
1050  template <typename OArrayType, ComponentIdType OSize>
1052  const ConstTupleReference<OArrayType, OSize>& other) noexcept
1053  {
1054  // Check that types are convertible:
1055  using OAPIType = GetAPIType<OArrayType>;
1056  static_assert(
1057  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1058 
1059  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1060  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
1061 
1062  std::copy_n(other.cbegin(), OSize, this->begin());
1063  return *this;
1064  }
1065 
1066  // Needs a runtime check:
1067  template <typename OArrayType, ComponentIdType OSize>
1069  const ConstTupleReference<OArrayType, OSize>& other) noexcept
1070  {
1071  // Check that types are convertible:
1072  using OAPIType = GetAPIType<OArrayType>;
1073  static_assert(
1074  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1075 
1077  other.size() == this->NumComps.value, "Cannot assign tuples with different sizes.");
1078 
1079  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
1080  return *this;
1081  }
1082 
1083  // skips some runtime checks when both sizes are fixed:
1084  template <typename OArrayType, ComponentIdType OSize>
1086  const TupleReference<OArrayType, OSize>& other) const noexcept
1087  {
1088  // Check that types are convertible:
1089  using OAPIType = GetAPIType<OArrayType>;
1090  static_assert(
1091  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1092 
1093  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1094  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
1095 
1096  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1097  }
1098 
1099  // Needs a runtime check:
1100  template <typename OArrayType, ComponentIdType OSize>
1102  const TupleReference<OArrayType, OSize>& other) const noexcept
1103  {
1104  // Check that types are convertible:
1105  using OAPIType = GetAPIType<OArrayType>;
1106  static_assert(
1107  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1108 
1110  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
1111 
1112  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1113  }
1114 
1115  // skips some runtime checks when both sizes are fixed:
1116  template <typename OArrayType, ComponentIdType OSize>
1118  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
1119  {
1120  // Check that types are convertible:
1121  using OAPIType = GetAPIType<OArrayType>;
1122  static_assert(
1123  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1124 
1125  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1126  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
1127 
1128  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1129  }
1130 
1131  // Needs a runtime check:
1132  template <typename OArrayType, ComponentIdType OSize>
1134  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
1135  {
1136  // Check that types are convertible:
1137  using OAPIType = GetAPIType<OArrayType>;
1138  static_assert(
1139  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1140 
1142  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
1143 
1144  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1145  }
1146 
1147  template <typename OArrayType, ComponentIdType OSize>
1149  {
1150  return !(*this == o);
1151  }
1152 
1153  template <typename OArray, ComponentIdType OSize>
1155  {
1156  return !(*this == o);
1157  }
1158 
1159  // skips some runtime checks:
1160  template <typename OArrayType, ComponentIdType OSize>
1162  TupleReference<OArrayType, OSize> other) noexcept
1163  {
1164  // Check that types are convertible:
1165  using OAPIType = GetAPIType<OArrayType>;
1166  static_assert(
1167  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
1168 
1169  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1170  static_assert(TupleSize == OSize, "Cannot swap tuples with different sizes.");
1171 
1172  std::swap_ranges(this->begin(), this->end(), other.begin());
1173  }
1174 
1175  // Needs a runtime check:
1176  template <typename OArrayType, ComponentIdType OSize>
1178  TupleReference<OArrayType, OSize> other) noexcept
1179  {
1180  // Check that types are convertible:
1181  using OAPIType = GetAPIType<OArrayType>;
1182  static_assert(
1183  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
1184 
1186  other.size() == this->NumComps.value, "Cannot swap tuples with different sizes.");
1187 
1188  std::swap_ranges(this->begin(), this->end(), other.begin());
1189  }
1190 
1191  friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept { a.swap(b); }
1192 
1193  template <typename OArray, ComponentIdType OSize>
1195  {
1196  a.swap(b);
1197  }
1198 
1201  {
1202  return reference{ this->Array, this->NumComps, this->TupleId, i };
1203  }
1204 
1207  {
1208  // Let the reference type do the lookup during implicit conversion.
1209  return const_reference{ this->Array, this->NumComps, this->TupleId, i };
1210  }
1211 
1213  void fill(const value_type& v) noexcept { std::fill(this->begin(), this->end(), v); }
1214 
1216  size_type size() const noexcept { return this->NumComps.value; }
1217 
1219  iterator begin() noexcept { return this->NewIterator(0); }
1221  iterator end() noexcept { return this->NewIterator(this->NumComps.value); }
1222 
1224  const_iterator begin() const noexcept { return this->NewConstIterator(0); }
1226  const_iterator end() const noexcept { return this->NewConstIterator(this->NumComps.value); }
1227 
1229  const_iterator cbegin() const noexcept { return this->NewConstIterator(0); }
1231  const_iterator cend() const noexcept { return this->NewConstIterator(this->NumComps.value); }
1232 
1233  friend struct ConstTupleReference<ArrayType, TupleSize>;
1234  friend struct TupleIterator<ArrayType, TupleSize>;
1235 
1236 protected:
1238  iterator NewIterator(ComponentIdType comp) const noexcept
1239  {
1240  VTK_ITER_ASSUME(this->NumComps.value > 0);
1241  return iterator{ this->Array, this->NumComps, this->TupleId, comp };
1242  }
1243 
1246  {
1247  VTK_ITER_ASSUME(this->NumComps.value > 0);
1248  return const_iterator{ this->Array, this->NumComps, this->TupleId, comp };
1249  }
1250 
1252  void CopyReference(const TupleReference& o) noexcept
1253  {
1254  // Must use same array, other array types may use different implementations.
1255  VTK_ITER_ASSERT(this->Array == o.Array, "Cannot copy reference objects between arrays.");
1256  this->NumComps = o.NumComps;
1257  this->TupleId = o.TupleId;
1258  }
1259 
1260  mutable ArrayType* Array;
1263 };
1264 
1265 //------------------------------------------------------------------------------
1266 // Const tuple iterator
1267 template <typename ArrayType, ComponentIdType TupleSize>
1268 struct ConstTupleIterator
1269 {
1270 private:
1271  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
1272  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
1273 
1274  using NumCompsType = GenericTupleSize<TupleSize>;
1275 
1276 public:
1277  using iterator_category = std::random_access_iterator_tag;
1282 
1284  ConstTupleIterator() noexcept = default;
1285 
1287  ConstTupleIterator(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
1288  : Ref(array, numComps, tupleId)
1289  {
1290  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
1291  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
1292  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
1293  "Const tuple iterator at invalid tuple id.");
1294  }
1295 
1298  : Ref{ o.Ref }
1299  {
1300  }
1301 
1303  ConstTupleIterator(const ConstTupleIterator& o) noexcept = default;
1306  {
1307  this->Ref.CopyReference(o.Ref);
1308  return *this;
1309  }
1310 
1312  ConstTupleIterator& operator++() noexcept // prefix
1313  {
1314  ++this->Ref.TupleId;
1316  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1317  "Const tuple iterator at invalid component id.");
1318  return *this;
1319  }
1320 
1322  ConstTupleIterator operator++(int) noexcept // postfix
1323  {
1324  return ConstTupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId++ };
1325  }
1326 
1328  ConstTupleIterator& operator--() noexcept // prefix
1329  {
1330  --this->Ref.TupleId;
1332  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1333  "Const tuple iterator at invalid component id.");
1334  return *this;
1335  }
1336 
1338  ConstTupleIterator operator--(int) noexcept // postfix
1339  {
1340  return ConstTupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId-- };
1341  }
1342 
1345  {
1346  return reference{ this->GetArray(), this->GetNumComps(), this->GetTupleId() + i };
1347  }
1348 
1350  reference operator*() noexcept { return this->Ref; }
1351 
1353  pointer operator->() noexcept { return this->Ref; }
1354 
1355 #define VTK_TMP_MAKE_OPERATOR(OP) \
1356  friend VTK_ITER_INLINE bool operator OP( \
1357  const ConstTupleIterator& lhs, const ConstTupleIterator& rhs) noexcept \
1358  { \
1359  VTK_ITER_ASSERT( \
1360  lhs.GetArray() == rhs.GetArray(), "Cannot compare iterators from different arrays."); \
1361  VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \
1362  VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \
1363  return lhs.GetTupleId() OP rhs.GetTupleId(); \
1364  }
1365 
1372 
1373 #undef VTK_TMP_MAKE_OPERATOR
1374 
1377  {
1378  this->Ref.TupleId += offset;
1380  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1381  "Const tuple iterator at invalid component id.");
1382  return *this;
1383  }
1384 
1386  const ConstTupleIterator& it, difference_type offset) noexcept
1387  {
1388  return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1389  }
1390 
1392  difference_type offset, const ConstTupleIterator& it) noexcept
1393  {
1394  return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1395  }
1396 
1399  {
1400  this->Ref.TupleId -= offset;
1402  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1403  "Const tuple iterator at invalid component id.");
1404  return *this;
1405  }
1406 
1408  const ConstTupleIterator& it, difference_type offset) noexcept
1409  {
1410  return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() - offset };
1411  }
1412 
1414  const ConstTupleIterator& it1, const ConstTupleIterator& it2) noexcept
1415  {
1416  VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(),
1417  "Cannot do math with tuple iterators from different "
1418  "arrays.");
1419  return it1.GetTupleId() - it2.GetTupleId();
1420  }
1421 
1423  {
1424  // Different arrays may use different iterator implementations.
1426  lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays.");
1427 
1428  using std::swap;
1429  swap(lhs.GetTupleId(), rhs.GetTupleId());
1430  }
1431 
1432 private:
1434  ArrayType* GetArray() const noexcept { return this->Ref.Array; }
1436  ArrayType*& GetArray() noexcept { return this->Ref.Array; }
1438  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
1440  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
1442  TupleIdType GetTupleId() const noexcept { return this->Ref.TupleId; }
1444  TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; }
1445 
1446  ConstTupleReference<ArrayType, TupleSize> Ref;
1447 };
1448 
1449 //------------------------------------------------------------------------------
1450 // Tuple iterator
1451 template <typename ArrayType, ComponentIdType TupleSize>
1452 struct TupleIterator
1453 {
1454 private:
1455  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
1456  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
1457 
1458  using NumCompsType = GenericTupleSize<TupleSize>;
1459 
1460 public:
1461  using iterator_category = std::random_access_iterator_tag;
1466 
1468  TupleIterator() noexcept = default;
1469 
1471  TupleIterator(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
1472  : Ref(array, numComps, tupleId)
1473  {
1474  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
1475  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
1477  tupleId >= 0 && tupleId <= array->GetNumberOfTuples(), "Tuple iterator at invalid tuple id.");
1478  }
1479 
1481  TupleIterator(const TupleIterator& o) noexcept = default;
1482 
1485  {
1486  this->Ref.CopyReference(o.Ref);
1487  return *this;
1488  }
1489 
1491  TupleIterator& operator++() noexcept // prefix
1492  {
1493  ++this->Ref.TupleId;
1495  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1496  "Tuple iterator at invalid component id.");
1497  return *this;
1498  }
1499 
1501  TupleIterator operator++(int) noexcept // postfix
1502  {
1503  return TupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId++ };
1504  }
1505 
1507  TupleIterator& operator--() noexcept // prefix
1508  {
1509  --this->Ref.TupleId;
1511  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1512  "Tuple iterator at invalid component id.");
1513  return *this;
1514  }
1515 
1517  TupleIterator operator--(int) noexcept // postfix
1518  {
1519  return TupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId-- };
1520  }
1521 
1524  {
1525  return reference{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId + i };
1526  }
1527 
1529  reference operator*() noexcept { return this->Ref; }
1530 
1532  pointer& operator->() noexcept { return this->Ref; }
1533 
1534 #define VTK_TMP_MAKE_OPERATOR(OP) \
1535  friend VTK_ITER_INLINE bool operator OP( \
1536  const TupleIterator& lhs, const TupleIterator& rhs) noexcept \
1537  { \
1538  VTK_ITER_ASSERT( \
1539  lhs.GetArray() == rhs.GetArray(), "Cannot compare iterators from different arrays."); \
1540  VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \
1541  VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \
1542  return lhs.GetTupleId() OP rhs.GetTupleId(); \
1543  }
1544 
1551 
1552 #undef VTK_TMP_MAKE_OPERATOR
1553 
1556  {
1557  this->Ref.TupleId += offset;
1559  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1560  "Tuple iterator at invalid component id.");
1561  return *this;
1562  }
1563 
1565  const TupleIterator& it, difference_type offset) noexcept
1566  {
1567  return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1568  }
1569 
1571  difference_type offset, const TupleIterator& it) noexcept
1572  {
1573  return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1574  }
1575 
1578  {
1579  this->Ref.TupleId -= offset;
1581  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1582  "Tuple iterator at invalid component id.");
1583  return *this;
1584  }
1585 
1587  const TupleIterator& it, difference_type offset) noexcept
1588  {
1589  return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() - offset };
1590  }
1591 
1593  const TupleIterator& it1, const TupleIterator& it2) noexcept
1594  {
1595  VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(),
1596  "Cannot do math with tuple iterators from different "
1597  "arrays.");
1598  return it1.GetTupleId() - it2.GetTupleId();
1599  }
1600 
1601  friend VTK_ITER_INLINE void swap(TupleIterator& lhs, TupleIterator& rhs) noexcept
1602  {
1603  // Different arrays may use different iterator implementations.
1605  lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays.");
1606 
1607  using std::swap;
1608  swap(lhs.GetTupleId(), rhs.GetTupleId());
1609  }
1610 
1611  friend struct ConstTupleIterator<ArrayType, TupleSize>;
1612  friend struct ConstTupleReference<ArrayType, TupleSize>;
1613 
1614 protected:
1616  ArrayType* GetArray() const noexcept { return this->Ref.Array; }
1618  ArrayType*& GetArray() noexcept { return this->Ref.Array; }
1620  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
1622  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
1624  TupleIdType GetTupleId() const noexcept { return this->Ref.TupleId; }
1626  TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; }
1627 
1629 };
1630 
1631 //------------------------------------------------------------------------------
1632 // Tuple range
1633 template <typename ArrayTypeT, ComponentIdType TupleSize>
1634 struct TupleRange
1635 {
1636 private:
1637  using NumCompsType = GenericTupleSize<TupleSize>;
1638  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
1639  static_assert(IsVtkDataArray<ArrayTypeT>::value, "Invalid array type.");
1640 
1641 public:
1642  using ArrayType = ArrayTypeT;
1653 
1654  // May be DynamicTupleSize, or the actual tuple size.
1655  constexpr static ComponentIdType TupleSizeTag = TupleSize;
1656 
1662 
1664  TupleRange() noexcept = default;
1665 
1667  TupleRange(ArrayType* arr, TupleIdType beginTuple, TupleIdType endTuple) noexcept
1668  : Array(arr)
1669  , NumComps(arr)
1670  , BeginTuple(beginTuple)
1671  , EndTuple(endTuple)
1672  {
1673  assert(this->Array);
1674  assert(beginTuple >= 0 && beginTuple <= endTuple);
1675  assert(endTuple >= 0 && endTuple <= this->Array->GetNumberOfTuples());
1676  }
1677 
1679  TupleRange GetSubRange(TupleIdType beginTuple = 0, TupleIdType endTuple = -1) const noexcept
1680  {
1681  const TupleIdType realBegin = this->BeginTuple + beginTuple;
1682  const TupleIdType realEnd = endTuple >= 0 ? this->BeginTuple + endTuple : this->EndTuple;
1683 
1684  return TupleRange{ this->Array, realBegin, realEnd };
1685  }
1686 
1688  ArrayType* GetArray() const noexcept { return this->Array; }
1690  ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
1692  TupleIdType GetBeginTupleId() const noexcept { return this->BeginTuple; }
1694  TupleIdType GetEndTupleId() const noexcept { return this->EndTuple; }
1695 
1697  size_type size() const noexcept { return this->EndTuple - this->BeginTuple; }
1698 
1700  iterator begin() noexcept { return this->NewIter(this->BeginTuple); }
1702  iterator end() noexcept { return this->NewIter(this->EndTuple); }
1703 
1705  const_iterator begin() const noexcept { return this->NewCIter(this->BeginTuple); }
1707  const_iterator end() const noexcept { return this->NewCIter(this->EndTuple); }
1708 
1710  const_iterator cbegin() const noexcept { return this->NewCIter(this->BeginTuple); }
1712  const_iterator cend() const noexcept { return this->NewCIter(this->EndTuple); }
1713 
1716  {
1717  return reference{ this->Array, this->NumComps, this->BeginTuple + i };
1718  }
1719 
1722  {
1723  return const_reference{ this->Array, this->NumComps, this->BeginTuple + i };
1724  }
1725 
1726 private:
1728  iterator NewIter(TupleIdType t) const { return iterator{ this->Array, this->NumComps, t }; }
1729 
1731  const_iterator NewCIter(TupleIdType t) const
1732  {
1733  return const_iterator{ this->Array, this->NumComps, t };
1734  }
1735 
1736  mutable ArrayType* Array{ nullptr };
1737  NumCompsType NumComps{};
1738  TupleIdType BeginTuple{ 0 };
1739  TupleIdType EndTuple{ 0 };
1740 };
1741 
1742 // Unimplemented, only used inside decltype in SelectTupleRange:
1743 template <typename ArrayType, ComponentIdType TupleSize>
1744 TupleRange<ArrayType, TupleSize> DeclareTupleRangeSpecialization(vtkDataArray*);
1745 
1746 } // end namespace detail
1747 } // end namespace vtk
1748 
1750 
1751 #endif // __VTK_WRAP__
1752 
1753 // VTK-HeaderTest-Exclude: vtkDataArrayTupleRange_Generic.h
const NumCompsType & GetNumComps() const noexcept
friend VTK_ITER_INLINE void swap(ComponentReference lhs, ComponentReference rhs) noexcept
VTK_ITER_INLINE APIType operator--(int) noexcept
VTK_ITER_INLINE void CopyReference(const TupleReference &o) noexcept
friend VTK_ITER_INLINE void swap(ComponentIterator &lhs, ComponentIterator &rhs) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
TupleReference< ArrayType, TupleSize > TupleReferenceType
VTK_ITER_INLINE TupleReference() noexcept
friend VTK_ITER_INLINE ComponentIterator operator+(const ComponentIterator &it, difference_type offset) noexcept
friend VTK_ITER_INLINE void swap(ConstComponentIterator &lhs, ConstComponentIterator &rhs) noexcept
friend VTK_ITER_INLINE ConstComponentIterator operator+(difference_type offset, const ConstComponentIterator &it) noexcept
VTK_ITER_INLINE iterator end() noexcept
friend VTK_ITER_INLINE ConstTupleIterator operator-(const ConstTupleIterator &it, difference_type offset) noexcept
const TupleIdType & GetTupleId() const noexcept
VTK_ITER_INLINE const pointer & operator->() const noexcept
vtkIdType TupleIdType
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, void > swap(TupleReference< OArrayType, OSize > other) noexcept
VTK_ITER_INLINE ConstComponentIterator(ArrayType *array, NumCompsType numComps, TupleIdType tupleId, ComponentIdType comp) noexcept
int ComponentIdType
friend VTK_ITER_INLINE ComponentIterator operator+(difference_type offset, const ComponentIterator &it) noexcept
VTK_ITER_INLINE APIType operator++(int) noexcept
VTK_ITER_INLINE reference operator*() const noexcept
friend VTK_ITER_INLINE ConstComponentIterator operator+(const ConstComponentIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE pointer & operator->() noexcept
VTK_ITER_INLINE TupleIterator & operator--() noexcept
TupleReference< ArrayType, TupleSize > Ref
friend VTK_ITER_INLINE ConstTupleIterator operator+(difference_type offset, const ConstTupleIterator &it) noexcept
friend VTK_ITER_INLINE TupleIterator operator-(const TupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE TupleRange() noexcept=default
VTK_ITER_INLINE void CopyReference(const ComponentReference &o) noexcept
VTK_ITER_INLINE NumCompsType GetNumComps() const noexcept
VTK_ITER_INLINE const_iterator begin() const noexcept
friend VTK_ITER_INLINE void swap(TupleIterator &lhs, TupleIterator &rhs) noexcept
VTK_ITER_INLINE TupleReference * operator->() noexcept
VTK_ITER_INLINE void GetTuple(APIType *tuple) const noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE iterator NewIterator(ComponentIdType comp) const noexcept
VTK_ITER_INLINE ConstTupleReference(const TupleReference< ArrayType, TupleSize > &o) noexcept
VTK_ITER_INLINE reference operator[](size_type i) noexcept
VTK_ITER_INLINE ConstComponentIterator operator--(int) noexcept
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
VTK_ITER_INLINE reference operator[](size_type i) noexcept
VTK_ITER_INLINE ComponentReference operator--() noexcept
VTK_ITER_INLINE ConstTupleIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE const_iterator cbegin() const noexcept
friend VTK_ITER_INLINE TupleIterator operator+(const TupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE TupleReference & operator=(const TupleReference &other) noexcept
typename std::enable_if< IsEitherTupleSizeDynamic< S1, S2 >::value, T >::type EnableIfEitherTupleSizeIsDynamic
VTK_ITER_INLINE ConstTupleIterator(const TupleIterator< ArrayType, TupleSize > &o) noexcept
VTK_ITER_INLINE ConstComponentReference(const ComponentReference< ArrayType, TupleSize > &o)
VTK_ITER_INLINE ComponentReference(ArrayType *array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept
VTK_ITER_INLINE ArrayType * GetArray() const noexcept
VTK_ITER_INLINE ConstTupleIterator() noexcept=default
friend VTK_ITER_INLINE TupleIterator operator+(difference_type offset, const TupleIterator &it) noexcept
VTK_ITER_INLINE const_iterator end() const noexcept
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
friend VTK_ITER_INLINE difference_type operator-(const TupleIterator &it1, const TupleIterator &it2) noexcept
VTK_ITER_INLINE ConstTupleIterator & operator=(const ConstTupleIterator &o) noexcept
VTK_ITER_INLINE iterator begin() noexcept
friend VTK_ITER_INLINE difference_type operator-(const ConstTupleIterator &it1, const ConstTupleIterator &it2) noexcept
VTK_ITER_INLINE const_iterator end() const noexcept
VTK_ITER_INLINE TupleRange GetSubRange(TupleIdType beginTuple=0, TupleIdType endTuple=-1) const noexcept
VTK_ITER_INLINE ConstComponentIterator & operator--() noexcept
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
VTK_ITER_INLINE const_iterator NewConstIterator(ComponentIdType comp) const noexcept
VTK_ITER_INLINE TupleIdType & GetTupleId() noexcept
VTK_ITER_INLINE reference operator[](difference_type i) const noexcept
friend VTK_ITER_INLINE ConstTupleIterator operator+(const ConstTupleIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE NumCompsType & GetNumComps() noexcept
VTK_ITER_INLINE ConstComponentIterator operator++(int) noexcept
VTK_ITER_INLINE ComponentReference operator=(const ComponentReference< OArray, OSize > &o) noexcept
VTK_ITER_INLINE bool operator!=(const ConstTupleReference< OArrayT, OSize > &o) const noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
This file contains a variety of metaprogramming constructs for working with vtkDataArrays.
friend VTK_ITER_INLINE void swap(APIType &lhs, ComponentReference rhs) noexcept
VTK_ITER_INLINE const_iterator cbegin() const noexcept
#define VTK_ITER_INLINE
VTK_ITER_INLINE bool operator!=(const TupleReference< OArrayType, OSize > &o) const noexcept
VTK_ITER_INLINE ArrayType *& GetArray() noexcept
friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference< OArray, OSize > b) noexcept
VTK_ITER_INLINE ConstTupleIterator operator--(int) noexcept
const ComponentIdType & GetComponentId() const noexcept
VTK_ITER_INLINE reference operator*() const noexcept
VTK_ITER_INLINE ConstComponentReference(ArrayType *array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept
friend VTK_ITER_INLINE ComponentIterator operator-(const ComponentIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE TupleIterator operator--(int) noexcept
VTK_ITER_INLINE pointer operator->() noexcept
VTK_ITER_INLINE ComponentIterator & operator+=(difference_type offset) noexcept
VTK_ITER_INLINE size_type size() const noexcept
VTK_ITER_INLINE TupleIdType GetTupleId() const noexcept
#define VTK_ITER_ASSUME
VTK_ITER_INLINE const TupleReference * operator->() const noexcept
VTK_ITER_INLINE ConstTupleIterator & operator+=(difference_type offset) noexcept
VTK_ITER_INLINE ComponentIterator operator++(int) noexcept
VTK_ITER_INLINE reference operator[](difference_type i) noexcept
VTK_ITER_INLINE TupleIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE TupleReference(ArrayType *array, NumCompsType numComps, TupleIdType tupleId) noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
#define VTK_ITER_OPTIMIZE_END
static constexpr ComponentIdType TupleSizeTag
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, TupleReference & > operator=(const TupleReference< OArrayType, OSize > &other) noexcept
abstract superclass for arrays of numeric data
Definition: vtkDataArray.h:55
friend VTK_ITER_INLINE void swap(ConstTupleIterator &lhs, ConstTupleIterator &rhs) noexcept
TupleIterator< ArrayType, TupleSize > TupleIteratorType
VTK_ITER_INLINE const_iterator cbegin() const noexcept
VTK_ITER_INLINE ConstComponentIterator & operator=(const ConstComponentIterator &o) noexcept=default
VTK_ITER_INLINE iterator end() noexcept
VTK_ITER_INLINE const_iterator NewConstIterator(ComponentIdType comp) const noexcept
VTK_ITER_INLINE void GetTuple(APIType *tuple) const noexcept
std::random_access_iterator_tag iterator_category
VTK_ITER_INLINE const_iterator begin() const noexcept
VTK_ITER_INLINE ConstComponentIterator & operator+=(difference_type offset) noexcept
friend VTK_ITER_INLINE ConstComponentIterator operator-(const ConstComponentIterator &it, difference_type offset) noexcept
VTK_ITER_INLINE void SetTuple(const APIType *tuple) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const ConstTupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE const_iterator cend() const noexcept
VTK_ITER_INLINE ConstComponentReference & operator=(ConstComponentReference &&o) noexcept
VTK_ITER_INLINE TupleIterator() noexcept=default
ComponentIdType & GetComponentId() noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
std::random_access_iterator_tag iterator_category
VTK_ITER_INLINE const_iterator begin() const noexcept
VTK_ITER_INLINE ConstComponentIterator(const ComponentIterator< ArrayType, TupleSize > &o) noexcept
VTK_ITER_INLINE reference operator[](difference_type i) noexcept
VTK_ITER_INLINE ComponentReference operator=(APIType val) noexcept
VTK_ITER_INLINE ComponentReference operator++() noexcept
ComponentReference< ArrayType, TupleSize > Ref
VTK_ITER_INLINE ComponentIterator() noexcept=default
VTK_ITER_INLINE ConstTupleIterator & operator++() noexcept
VTK_ITER_INLINE ConstTupleReference(ArrayType *array, NumCompsType numComps, TupleIdType tupleId) noexcept
VTK_ITER_INLINE ArrayType * GetArray() const noexcept
VTK_ITER_INLINE ConstTupleIterator operator++(int) noexcept
VTK_ITER_INLINE reference operator*() noexcept
VTK_ITER_INLINE size_type size() const noexcept
#define VTK_ITER_ASSERT(x, msg)
TupleRange< AOSArrayType, TupleSize > DeclareTupleRangeSpecialization(ArrayType *)
VTK_ITER_INLINE size_type size() const noexcept
VTK_ITER_INLINE ComponentIdType GetTupleSize() const noexcept
ConstTupleIterator< ArrayType, TupleSize > ConstTupleIteratorType
VTK_ITER_INLINE ConstTupleIterator & operator--() noexcept
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, TupleReference & > operator=(const ConstTupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
VTK_ITER_INLINE TupleIterator & operator=(const TupleIterator &o) noexcept
VTK_ITER_INLINE ConstComponentIterator & operator-=(difference_type offset) noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
#define VTK_TMP_MAKE_OPERATOR(OP)
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, TupleReference & > operator=(const TupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE TupleIterator & operator++() noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, bool > operator==(const TupleReference< OArrayType, OSize > &other) const noexcept
VTK_ITER_INLINE const ConstTupleReference * operator->() const noexcept
VTK_ITER_INLINE void CopyReference(const ConstTupleReference &o) noexcept
VTK_ITER_INLINE void fill(const value_type &v) noexcept
VTK_ITER_INLINE const_iterator end() const noexcept
VTK_ITER_INLINE TupleIdType GetEndTupleId() const noexcept
typename detail::GetAPITypeImpl< ArrayType >::APIType GetAPIType
VTK_ITER_INLINE iterator begin() noexcept
friend VTK_ITER_INLINE difference_type operator-(const ConstComponentIterator &it1, const ConstComponentIterator &it2) noexcept
friend VTK_ITER_INLINE void swap(ComponentReference lhs, ComponentReference< OArray, OSize > rhs) noexcept
VTK_ITER_INLINE TupleIterator operator++(int) noexcept
VTK_ITER_INLINE ComponentIterator & operator-=(difference_type offset) noexcept
friend VTK_ITER_INLINE difference_type operator-(const ComponentIterator &it1, const ComponentIterator &it2) noexcept
VTK_ITER_INLINE const_reference operator[](size_type i) const noexcept
std::random_access_iterator_tag iterator_category
ConstTupleReference< ArrayType, TupleSize > ConstTupleReferenceType
VTK_ITER_INLINE ComponentIterator operator--(int) noexcept
VTK_ITER_INLINE reference operator[](difference_type i) const noexcept
VTK_ITER_INLINE TupleIterator & operator+=(difference_type offset) noexcept
#define VTK_ITER_OPTIMIZE_START
VTK_ITER_INLINE ConstTupleReference & operator=(const ConstTupleReference &) noexcept=default
VTK_ITER_INLINE ConstComponentIterator & operator++() noexcept
VTK_ITER_INLINE ComponentIterator & operator=(const ComponentIterator &o) noexcept
friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept
VTK_ITER_INLINE TupleIdType GetBeginTupleId() const noexcept
friend VTK_ITER_INLINE void swap(ComponentReference lhs, APIType &rhs) noexcept
std::random_access_iterator_tag iterator_category
VTK_ITER_INLINE EnableIfStaticTupleSizes< TupleSize, OSize, void > swap(TupleReference< OArrayType, OSize > other) noexcept
Efficient templated access to vtkDataArray.
#define VTK_REF_OP_OVERLOADS(Op, ImplOp)
VTK_ITER_INLINE reference operator*() noexcept
VTK_ITER_INLINE ComponentIterator & operator--() noexcept
VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic< TupleSize, OSize, TupleReference & > operator=(const ConstTupleReference< OArrayType, OSize > &other) noexcept
VTK_ITER_INLINE ComponentIterator & operator++() noexcept
VTK_ITER_INLINE bool operator!=(const ConstTupleReference< OArray, OSize > &o) const noexcept
typename std::enable_if< AreStaticTupleSizes< S1, S2 >::value, T >::type EnableIfStaticTupleSizes
VTK_ITER_INLINE ComponentReference operator=(ComponentReference &&o) noexcept