VTK  9.1.0
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 
32 #ifndef __VTK_WRAP__
33 
35 
36 namespace vtk
37 {
38 
39 namespace detail
40 {
41 
42 // Forward decs for friends/args
43 template <typename ArrayType, ComponentIdType>
44 struct ConstComponentReference;
45 template <typename ArrayType, ComponentIdType>
46 struct ComponentReference;
47 template <typename ArrayType, ComponentIdType>
48 struct ConstComponentIterator;
49 template <typename ArrayType, ComponentIdType>
50 struct ComponentIterator;
51 template <typename ArrayType, ComponentIdType>
52 struct ConstTupleReference;
53 template <typename ArrayType, ComponentIdType>
54 struct TupleReference;
55 template <typename ArrayType, ComponentIdType>
56 struct ConstTupleIterator;
57 template <typename ArrayType, ComponentIdType>
58 struct TupleIterator;
59 template <typename ArrayType, ComponentIdType>
60 struct TupleRange;
61 
62 //------------------------------------------------------------------------------
63 // Const component reference
64 template <typename ArrayType, ComponentIdType TupleSize>
66 {
67 private:
68  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
69  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
70 
72  using APIType = GetAPIType<ArrayType>;
73 
74 public:
75  using value_type = APIType;
76 
79  : Array{ nullptr }
80  , NumComps{}
81  , TupleId{ 0 }
82  , ComponentId{ 0 }
83  {
84  }
85 
88  ArrayType* array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept
89  : Array{ array }
90  , NumComps{ numComps }
91  , TupleId{ tuple }
92  , ComponentId{ comp }
93  {
94  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
95  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
97  tuple >= 0 && tuple <= array->GetNumberOfTuples(), "Invalid tuple accessed by iterator.");
98  VTK_ITER_ASSERT(comp >= 0 && comp <= array->GetNumberOfComponents(),
99  "Invalid component accessed by iterator.");
100  }
101 
104  : Array{ o.Array }
105  , NumComps{ o.NumComps }
106  , TupleId{ o.TupleId }
107  , ComponentId{ o.ComponentId }
108  {
109  }
110 
112  ConstComponentReference(const ConstComponentReference& o) noexcept = default;
113 
116 
119  {
120  VTK_ITER_ASSERT(!this->Array, "Const reference already initialized.");
121  // Initialize the reference.
122  this->Array = o.Array;
123  this->NumComps = o.NumComps;
124  this->TupleId = o.TupleId;
125  this->ComponentId = o.ComponentId;
126  }
127 
130  {
131  VTK_ITER_ASSERT(!this->Array, "Const reference already initialized.");
132  // Initialize the reference.
133  this->Array = std::move(o.Array);
134  this->NumComps = std::move(o.NumComps);
135  this->TupleId = std::move(o.TupleId);
136  this->ComponentId = std::move(o.ComponentId);
137  }
138 
140  operator APIType() const noexcept
141  {
142  VTK_ITER_ASSUME(this->NumComps.value > 0);
143  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
145  return acc.Get(this->TupleId, this->ComponentId);
146  }
147 
148 protected:
149  mutable ArrayType* Array;
153 };
154 
155 //------------------------------------------------------------------------------
156 // Component reference
157 template <typename ArrayType, ComponentIdType TupleSize>
159 {
160 private:
161  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
162  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
163 
165  using APIType = GetAPIType<ArrayType>;
166 
167 public:
168  using value_type = APIType;
169 
172  : Array{ nullptr }
173  , NumComps{}
174  , TupleId{ 0 }
175  , ComponentId{ 0 }
176  {
177  }
178 
181  ArrayType* array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept
182  : Array{ array }
183  , NumComps{ numComps }
184  , TupleId{ tuple }
185  , ComponentId{ comp }
186  {
187  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
188  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
190  tuple >= 0 && tuple <= array->GetNumberOfTuples(), "Invalid tuple accessed by iterator.");
191  VTK_ITER_ASSERT(comp >= 0 && comp <= array->GetNumberOfComponents(),
192  "Invalid component accessed by iterator.");
193  }
194 
196  ComponentReference(const ComponentReference& o) noexcept = default;
198  ComponentReference(ComponentReference&& o) noexcept = default;
199 
202  {
203  if (this->Array)
204  { // Already initialized. Assign the value, not the reference
205  return *this = static_cast<APIType>(o);
206  }
207  else
208  { // Initialize the reference.
209  this->Array = o.Array;
210  this->NumComps = o.NumComps;
211  this->TupleId = o.TupleId;
212  this->ComponentId = o.ComponentId;
213 
214  return *this;
215  }
216  }
217 
220  {
221  if (this->Array)
222  { // Already initialized. Assign the value, not the reference
223  return *this = std::move(static_cast<APIType>(o));
224  }
225  else
226  { // Initialize the reference.
227  this->Array = std::move(o.Array);
228  this->NumComps = std::move(o.NumComps);
229  this->TupleId = std::move(o.TupleId);
230  this->ComponentId = std::move(o.ComponentId);
231 
232  return *this;
233  }
234  }
235 
236  template <typename OArray, ComponentIdType OSize>
238  { // Always copy the value for different reference types:
239  const APIType tmp = o;
240  return *this = std::move(tmp);
241  }
242 
244  operator APIType() const noexcept
245  {
246  VTK_ITER_ASSUME(this->NumComps.value > 0);
247  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
249  return acc.Get(this->TupleId, this->ComponentId);
250  }
251 
253  ComponentReference operator=(APIType val) noexcept
254  {
255  VTK_ITER_ASSUME(this->NumComps.value > 0);
256  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
258  acc.Set(this->TupleId, this->ComponentId, val);
259  return *this;
260  }
261 
263  { // Swap values, not references:
264  APIType tmp = std::move(static_cast<APIType>(lhs));
265  lhs = std::move(static_cast<APIType>(rhs));
266  rhs = std::move(tmp);
267  }
268 
269  template <typename OArray, ComponentIdType OSize>
270  friend VTK_ITER_INLINE void swap(
272  { // Swap values, not references:
273  using OAPIType = GetAPIType<OArray>;
274  static_assert(
275  std::is_same<APIType, OAPIType>::value, "Cannot swap components with different types.");
276 
277  APIType tmp = std::move(static_cast<APIType>(lhs));
278  lhs = std::move(static_cast<APIType>(rhs));
279  rhs = std::move(tmp);
280  }
281 
282  friend VTK_ITER_INLINE void swap(ComponentReference lhs, APIType& rhs) noexcept
283  {
284  APIType tmp = std::move(static_cast<APIType>(lhs));
285  lhs = std::move(rhs);
286  rhs = std::move(tmp);
287  }
288 
289  friend VTK_ITER_INLINE void swap(APIType& lhs, ComponentReference rhs) noexcept
290  {
291  APIType tmp = std::move(lhs);
292  lhs = std::move(static_cast<APIType>(rhs));
293  rhs = std::move(tmp);
294  }
295 
297  ComponentReference operator++() noexcept // prefix
298  {
299  const APIType newVal = *this + 1;
300  *this = newVal;
301  return *this;
302  }
303 
305  APIType operator++(int) noexcept // postfix
306  {
307  const APIType retVal = *this;
308  *this = *this + 1;
309  return retVal;
310  }
311 
313  ComponentReference operator--() noexcept // prefix
314  {
315  const APIType newVal = *this - 1;
316  *this = newVal;
317  return *this;
318  }
319 
321  APIType operator--(int) noexcept // postfix
322  {
323  const APIType retVal = *this;
324  *this = *this - 1;
325  return retVal;
326  }
327 
328 #define VTK_REF_OP_OVERLOADS(Op, ImplOp) \
329  friend VTK_ITER_INLINE ComponentReference operator Op( \
330  ComponentReference lhs, APIType val) noexcept \
331  { \
332  const APIType newVal = lhs ImplOp val; \
333  lhs = newVal; \
334  return lhs; \
335  } \
336  friend VTK_ITER_INLINE ComponentReference operator Op( \
337  ComponentReference lhs, ComponentReference val) noexcept \
338  { \
339  const APIType newVal = lhs ImplOp val; \
340  lhs = newVal; \
341  return lhs; \
342  } \
343  friend VTK_ITER_INLINE APIType& operator Op(APIType& lhs, ComponentReference val) noexcept \
344  { \
345  const APIType newVal = lhs ImplOp val; \
346  lhs = newVal; \
347  return lhs; \
348  }
349 
350  VTK_REF_OP_OVERLOADS(+=, +)
351  VTK_REF_OP_OVERLOADS(-=, -)
352  VTK_REF_OP_OVERLOADS(*=, *)
353  VTK_REF_OP_OVERLOADS(/=, /)
354 
355 #undef VTK_REF_OP_OVERLOADS
356 
357  friend struct ConstComponentReference<ArrayType, TupleSize>;
358  friend struct ComponentIterator<ArrayType, TupleSize>;
359 
360 protected:
362  void CopyReference(const ComponentReference& o) noexcept
363  {
364  this->Array = o.Array;
365  this->NumComps = o.NumComps;
366  this->TupleId = o.TupleId;
367  this->ComponentId = o.ComponentId;
368  }
369 
370  mutable ArrayType* Array;
374 };
375 
376 //------------------------------------------------------------------------------
377 // Const component iterator
378 template <typename ArrayType, ComponentIdType TupleSize>
380 {
381 private:
382  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
383  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
384 
386 
387 public:
388  using iterator_category = std::random_access_iterator_tag;
391  using pointer = void;
393 
396  : Array{ nullptr }
397  , TupleId{ 0 }
398  , ComponentId{ 0 }
399  {
400  }
401 
404  ArrayType* array, NumCompsType numComps, TupleIdType tupleId, ComponentIdType comp) noexcept
405  : Array(array)
406  , NumComps(numComps)
407  , TupleId(tupleId)
408  , ComponentId(comp)
409  {
410  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
411  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
412  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
413  "Const component iterator at invalid tuple id.");
414  VTK_ITER_ASSERT(comp >= 0 && comp <= this->NumComps.value,
415  "Const component iterator at invalid component id.");
416  }
417 
420  : Array{ o.GetArray() }
421  , NumComps{ o.GetNumComps() }
422  , TupleId{ o.GetTupleId() }
423  , ComponentId{ o.GetComponentId() }
424  {
425  }
426 
428  ConstComponentIterator(const ConstComponentIterator& o) noexcept = default;
431 
433  ConstComponentIterator& operator++() noexcept // prefix
434  {
435  ++this->ComponentId;
436  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
437  "Const component iterator at invalid component id.");
438  return *this;
439  }
440 
442  ConstComponentIterator operator++(int) noexcept // postfix
443  {
444  return ConstComponentIterator{ this->Array, this->NumComps, this->TupleId,
445  this->ComponentId++ };
446  }
447 
449  ConstComponentIterator& operator--() noexcept // prefix
450  {
451  --this->ComponentId;
452  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
453  "Const component iterator at invalid component id.");
454  return *this;
455  }
456 
458  ConstComponentIterator operator--(int) noexcept // postfix
459  {
460  return ConstComponentIterator{ this->Array, this->NumComps, this->TupleId,
461  this->ComponentId-- };
462  }
463 
466  {
467  return reference{ this->Array, this->NumComps, this->TupleId, this->ComponentId + i };
468  }
469 
471  reference operator*() const noexcept
472  {
473  return reference{ this->Array, this->NumComps, this->TupleId, this->ComponentId };
474  }
475 
476 #define VTK_TMP_MAKE_OPERATOR(OP) \
477  friend VTK_ITER_INLINE bool operator OP( \
478  const ConstComponentIterator& lhs, const ConstComponentIterator& rhs) noexcept \
479  { \
480  VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Mismatched arrays in iterator comparison."); \
481  VTK_ITER_ASSERT(lhs.TupleId == rhs.TupleId, "Mismatched tuple ids in iterator comparison."); \
482  VTK_ITER_ASSUME(lhs.NumComps.value > 0); \
483  VTK_ITER_ASSUME(lhs.NumComps.value == rhs.NumComps.value); \
484  return lhs.ComponentId OP rhs.ComponentId; \
485  }
486 
493 
494 #undef VTK_TMP_MAKE_OPERATOR
495 
498  {
499  this->ComponentId += offset;
500  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
501  "Const component iterator at invalid component id.");
502  return *this;
503  }
504 
506  const ConstComponentIterator& it, difference_type offset) noexcept
507  {
508  return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId + offset };
509  }
510 
512  difference_type offset, const ConstComponentIterator& it) noexcept
513  {
514  return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId + offset };
515  }
516 
519  {
520  this->ComponentId -= offset;
521  VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value,
522  "Const component iterator at invalid component id.");
523  return *this;
524  }
525 
527  const ConstComponentIterator& it, difference_type offset) noexcept
528  {
529  return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId - offset };
530  }
531 
533  const ConstComponentIterator& it1, const ConstComponentIterator& it2) noexcept
534  {
535  VTK_ITER_ASSERT(it1.Array == it2.Array, "Cannot do math with iterators from different arrays.");
536  VTK_ITER_ASSERT(it1.TupleId == it2.TupleId,
537  "Cannot do math with component iterators from different "
538  "tuples.");
539  return it1.ComponentId - it2.ComponentId;
540  }
541 
542  friend VTK_ITER_INLINE void swap(
544  {
545  // Different arrays may use different iterator implementations.
546  VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Cannot swap iterators from different arrays.");
547 
548  using std::swap;
549  swap(lhs.TupleId, rhs.TupleId);
550  swap(lhs.ComponentId, rhs.ComponentId);
551  }
552 
553 private:
554  mutable ArrayType* Array;
555  NumCompsType NumComps;
556  TupleIdType TupleId;
557  ComponentIdType ComponentId;
558 };
559 
560 //------------------------------------------------------------------------------
561 // Component iterator
562 template <typename ArrayType, ComponentIdType TupleSize>
564 {
565 private:
566  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
567  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
568 
570  using APIType = GetAPIType<ArrayType>;
571 
572 public:
573  using iterator_category = std::random_access_iterator_tag;
574  using value_type = APIType;
578 
580  ComponentIterator() noexcept = default;
581 
584  ArrayType* array, NumCompsType numComps, TupleIdType tupleId, ComponentIdType comp) noexcept
585  : Ref(array, numComps, tupleId, comp)
586  {
587  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
588  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
589  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
590  "Component iterator at invalid tuple id.");
592  comp >= 0 && comp <= numComps.value, "Component iterator at invalid component id.");
593  }
594 
596  ComponentIterator(const ComponentIterator& o) noexcept = default;
597 
600  {
601  this->Ref.CopyReference(o.Ref);
602  return *this;
603  }
604 
606  ComponentIterator& operator++() noexcept // prefix
607  {
608  ++this->Ref.ComponentId;
609  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
610  "Component iterator at invalid component id.");
611  return *this;
612  }
613 
615  ComponentIterator operator++(int) noexcept // postfix
616  {
617  return ComponentIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId,
618  this->Ref.ComponentId++ };
619  }
620 
622  ComponentIterator& operator--() noexcept // prefix
623  {
624  --this->Ref.ComponentId;
625  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
626  "Component iterator at invalid component id.");
627  return *this;
628  }
629 
631  ComponentIterator operator--(int) noexcept // postfix
632  {
633  return ComponentIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId,
634  this->Ref.ComponentId-- };
635  }
636 
639  {
640  return reference{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId,
641  this->Ref.ComponentId + i };
642  }
643 
645  reference operator*() const noexcept { return this->Ref; }
646 
648  const pointer& operator->() const noexcept { return this->Ref; }
649 
650 #define VTK_TMP_MAKE_OPERATOR(OP) \
651  friend VTK_ITER_INLINE bool operator OP( \
652  const ComponentIterator& lhs, const ComponentIterator& rhs) noexcept \
653  { \
654  VTK_ITER_ASSERT( \
655  lhs.GetArray() == rhs.GetArray(), "Mismatched arrays in iterator comparison."); \
656  VTK_ITER_ASSERT( \
657  lhs.GetTupleId() == rhs.GetTupleId(), "Mismatched tuple ids in iterator comparison."); \
658  VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \
659  VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \
660  return lhs.GetComponentId() OP rhs.GetComponentId(); \
661  }
662 
669 
670 #undef VTK_TMP_MAKE_OPERATOR
671 
674  {
675  this->Ref.ComponentId += offset;
676  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
677  "Component iterator at invalid component id.");
678  return *this;
679  }
680 
682  const ComponentIterator& it, difference_type offset) noexcept
683  {
684  return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(),
685  it.GetComponentId() + offset };
686  }
687 
689  difference_type offset, const ComponentIterator& it) noexcept
690  {
691  return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(),
692  it.GetComponentId() + offset };
693  }
694 
697  {
698  this->Ref.ComponentId -= offset;
699  VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value,
700  "Component iterator at invalid component id.");
701  return *this;
702  }
703 
705  const ComponentIterator& it, difference_type offset) noexcept
706  {
707  return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(),
708  it.GetComponentId() - offset };
709  }
710 
712  const ComponentIterator& it1, const ComponentIterator& it2) noexcept
713  {
714  VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(),
715  "Cannot do math with component iterators from different "
716  "arrays.");
717  VTK_ITER_ASSERT(it1.GetTupleId() == it2.GetTupleId(),
718  "Cannot do math with component iterators from different "
719  "tuples.");
720  return it1.GetComponentId() - it2.GetComponentId();
721  }
722 
723  friend VTK_ITER_INLINE void swap(ComponentIterator& lhs, ComponentIterator& rhs) noexcept
724  {
725  // Different arrays may use different iterator implementations.
727  lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays.");
728 
729  using std::swap;
730  swap(lhs.GetTupleId(), rhs.GetTupleId());
731  swap(lhs.GetComponentId(), rhs.GetComponentId());
732  }
733 
734  friend struct ConstComponentIterator<ArrayType, TupleSize>;
735 
736 protected:
737  // Needed for access from friend functions. We could just store the array
738  // and ID here instead of the ref, but meh.
739  ArrayType* GetArray() const noexcept { return this->Ref.Array; }
740  TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; }
741  const TupleIdType& GetTupleId() const noexcept { return this->Ref.TupleId; }
742  ComponentIdType& GetComponentId() noexcept { return this->Ref.ComponentId; }
743  const ComponentIdType& GetComponentId() const noexcept { return this->Ref.ComponentId; }
744  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
745  const NumCompsType& GetNumComps() const noexcept { return this->Ref.NumComps; }
746 
748 };
749 
750 //------------------------------------------------------------------------------
751 // Const tuple reference
752 template <typename ArrayType, ComponentIdType TupleSize>
754 {
755 private:
756  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
757  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
758 
760  using APIType = GetAPIType<ArrayType>;
761 
762 public:
764  using value_type = APIType;
768 
771  : Array(nullptr)
772  , TupleId(0)
773  {
774  }
775 
777  ConstTupleReference(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
778  : Array(array)
779  , NumComps(numComps)
780  , TupleId(tupleId)
781  {
782  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
783  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
784  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
785  "Const tuple reference at invalid tuple id.");
786  }
787 
790  : Array{ o.Array }
791  , NumComps{ o.NumComps }
792  , TupleId{ o.TupleId }
793  {
794  }
795 
797  ConstTupleReference(const ConstTupleReference&) noexcept = default;
800 
801  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
803  ConstTupleReference* operator->() noexcept { return this; }
805  const ConstTupleReference* operator->() const noexcept { return this; }
806 
807  // Caller must ensure that there are size() elements in array.
809  void GetTuple(APIType* tuple) const noexcept
810  {
811  VTK_ITER_ASSUME(this->NumComps.value > 0);
812  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
814  acc.Get(this->TupleId, tuple);
815  }
816 
817  // skips some runtime checks when both sizes are fixed:
818  template <typename OArrayType, ComponentIdType OSize>
820  const TupleReference<OArrayType, OSize>& other) const noexcept
821  {
822  // Check that types are convertible:
823  using OAPIType = GetAPIType<OArrayType>;
824  static_assert(
825  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
826 
827  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
828  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
829 
830  return std::equal(this->cbegin(), this->cend(), other.cbegin());
831  }
832 
833  // Needs a runtime check:
834  template <typename OArrayType, ComponentIdType OSize>
836  const TupleReference<OArrayType, OSize>& other) const noexcept
837  {
838  // Check that types are convertible:
839  using OAPIType = GetAPIType<OArrayType>;
840  static_assert(
841  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
842 
844  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
845 
846  return std::equal(this->cbegin(), this->cend(), other.cbegin());
847  }
848 
849  // skips some runtime checks when both sizes are fixed:
850  template <typename OArrayType, ComponentIdType OSize>
852  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
853  {
854  // Check that types are convertible:
855  using OAPIType = GetAPIType<OArrayType>;
856  static_assert(
857  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
858 
859  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
860  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
861 
862  return std::equal(this->cbegin(), this->cend(), other.cbegin());
863  }
864 
865  // Needs a runtime check:
866  template <typename OArrayType, ComponentIdType OSize>
868  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
869  {
870  // Check that types are convertible:
871  using OAPIType = GetAPIType<OArrayType>;
872  static_assert(
873  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
874 
876  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
877 
878  return std::equal(this->cbegin(), this->cend(), other.cbegin());
879  }
880 
881  template <typename OArrayType, ComponentIdType OSize>
883  {
884  return !(*this == o);
885  }
886 
887  template <typename OArrayT, ComponentIdType OSize>
889  {
890  return !(*this == o);
891  }
892 
895  {
896  return const_reference{ this->Array, this->NumComps, this->TupleId, i };
897  }
898 
900  size_type size() const noexcept { return this->NumComps.value; }
901 
903  const_iterator begin() const noexcept { return this->NewConstIterator(0); }
905  const_iterator end() const noexcept { return this->NewConstIterator(this->NumComps.value); }
906 
908  const_iterator cbegin() const noexcept { return this->NewConstIterator(0); }
910  const_iterator cend() const noexcept { return this->NewConstIterator(this->NumComps.value); }
911 
912  friend struct ConstTupleIterator<ArrayType, TupleSize>;
913 
914 protected:
915  // Intentionally hidden:
917  ConstTupleReference& operator=(const ConstTupleReference&) noexcept = default;
918 
921  {
922  VTK_ITER_ASSUME(this->NumComps.value > 0);
923  return const_iterator{ this->Array, this->NumComps, this->TupleId, comp };
924  }
925 
927  void CopyReference(const ConstTupleReference& o) noexcept
928  {
929  // Must use same array, other array types may use different implementations.
930  VTK_ITER_ASSERT(this->Array == o.Array, "Cannot copy reference objects between arrays.");
931  this->NumComps = o.NumComps;
932  this->TupleId = o.TupleId;
933  }
934 
935  mutable ArrayType* Array;
938 };
939 
940 //------------------------------------------------------------------------------
941 // Tuple reference
942 template <typename ArrayType, ComponentIdType TupleSize>
944 {
945 private:
946  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
947  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
948 
950  using APIType = GetAPIType<ArrayType>;
951 
952 public:
954  using value_type = APIType;
959 
961  TupleReference() noexcept
962  : Array(nullptr)
963  , TupleId(0)
964  {
965  }
966 
968  TupleReference(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
969  : Array(array)
970  , NumComps(numComps)
971  , TupleId(tupleId)
972  {
973  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
974  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
975  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
976  "Tuple reference at invalid tuple id.");
977  }
978 
980  TupleReference(const TupleReference&) = default;
983 
984  // Allow this type to masquerade as a pointer, so that tupleIiter->foo works.
986  TupleReference* operator->() noexcept { return this; }
988  const TupleReference* operator->() const noexcept { return this; }
989 
990  // Caller must ensure that there are size() elements in array.
992  void GetTuple(APIType* tuple) const noexcept
993  {
994  VTK_ITER_ASSUME(this->NumComps.value > 0);
995  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
997  acc.Get(this->TupleId, tuple);
998  }
999 
1000  // Caller must ensure that there are size() elements in array.
1002  void SetTuple(const APIType* tuple) noexcept
1003  {
1004  VTK_ITER_ASSUME(this->NumComps.value > 0);
1005  VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value);
1007  acc.Set(this->TupleId, tuple);
1008  }
1009 
1011  TupleReference& operator=(const TupleReference& other) noexcept
1012  {
1013  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
1014  return *this;
1015  }
1016 
1017  // skips some runtime checks when both sizes are fixed:
1018  template <typename OArrayType, ComponentIdType OSize>
1020  const TupleReference<OArrayType, OSize>& other) noexcept
1021  {
1022  // Check that types are convertible:
1023  using OAPIType = GetAPIType<OArrayType>;
1024  static_assert(
1025  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1026 
1027  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1028  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
1029 
1030  std::copy_n(other.cbegin(), OSize, this->begin());
1031  return *this;
1032  }
1033 
1034  // Needs a runtime check:
1035  template <typename OArrayType, ComponentIdType OSize>
1037  const TupleReference<OArrayType, OSize>& other) noexcept
1038  {
1039  // Check that types are convertible:
1040  using OAPIType = GetAPIType<OArrayType>;
1041  static_assert(
1042  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1043 
1045  other.size() == this->NumComps.value, "Cannot assign tuples with different sizes.");
1046 
1047  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
1048  return *this;
1049  }
1050 
1051  // skips some runtime checks when both sizes are fixed:
1052  template <typename OArrayType, ComponentIdType OSize>
1054  const ConstTupleReference<OArrayType, OSize>& other) noexcept
1055  {
1056  // Check that types are convertible:
1057  using OAPIType = GetAPIType<OArrayType>;
1058  static_assert(
1059  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1060 
1061  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1062  static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes.");
1063 
1064  std::copy_n(other.cbegin(), OSize, this->begin());
1065  return *this;
1066  }
1067 
1068  // Needs a runtime check:
1069  template <typename OArrayType, ComponentIdType OSize>
1071  const ConstTupleReference<OArrayType, OSize>& other) noexcept
1072  {
1073  // Check that types are convertible:
1074  using OAPIType = GetAPIType<OArrayType>;
1075  static_assert(
1076  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples.");
1077 
1079  other.size() == this->NumComps.value, "Cannot assign tuples with different sizes.");
1080 
1081  std::copy_n(other.cbegin(), this->NumComps.value, this->begin());
1082  return *this;
1083  }
1084 
1085  // skips some runtime checks when both sizes are fixed:
1086  template <typename OArrayType, ComponentIdType OSize>
1088  const TupleReference<OArrayType, OSize>& other) const noexcept
1089  {
1090  // Check that types are convertible:
1091  using OAPIType = GetAPIType<OArrayType>;
1092  static_assert(
1093  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1094 
1095  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1096  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
1097 
1098  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1099  }
1100 
1101  // Needs a runtime check:
1102  template <typename OArrayType, ComponentIdType OSize>
1104  const TupleReference<OArrayType, OSize>& other) const noexcept
1105  {
1106  // Check that types are convertible:
1107  using OAPIType = GetAPIType<OArrayType>;
1108  static_assert(
1109  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1110 
1112  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
1113 
1114  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1115  }
1116 
1117  // skips some runtime checks when both sizes are fixed:
1118  template <typename OArrayType, ComponentIdType OSize>
1120  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
1121  {
1122  // Check that types are convertible:
1123  using OAPIType = GetAPIType<OArrayType>;
1124  static_assert(
1125  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1126 
1127  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1128  static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes.");
1129 
1130  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1131  }
1132 
1133  // Needs a runtime check:
1134  template <typename OArrayType, ComponentIdType OSize>
1136  const ConstTupleReference<OArrayType, OSize>& other) const noexcept
1137  {
1138  // Check that types are convertible:
1139  using OAPIType = GetAPIType<OArrayType>;
1140  static_assert(
1141  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples.");
1142 
1144  other.size() == this->NumComps.value, "Cannot compare tuples with different sizes.");
1145 
1146  return std::equal(this->cbegin(), this->cend(), other.cbegin());
1147  }
1148 
1149  template <typename OArrayType, ComponentIdType OSize>
1151  {
1152  return !(*this == o);
1153  }
1154 
1155  template <typename OArray, ComponentIdType OSize>
1157  {
1158  return !(*this == o);
1159  }
1160 
1161  // skips some runtime checks:
1162  template <typename OArrayType, ComponentIdType OSize>
1164  TupleReference<OArrayType, OSize> other) noexcept
1165  {
1166  // Check that types are convertible:
1167  using OAPIType = GetAPIType<OArrayType>;
1168  static_assert(
1169  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
1170 
1171  // SFINAE guarantees that the tuple sizes are not dynamic in this overload:
1172  static_assert(TupleSize == OSize, "Cannot swap tuples with different sizes.");
1173 
1174  std::swap_ranges(this->begin(), this->end(), other.begin());
1175  }
1176 
1177  // Needs a runtime check:
1178  template <typename OArrayType, ComponentIdType OSize>
1180  TupleReference<OArrayType, OSize> other) noexcept
1181  {
1182  // Check that types are convertible:
1183  using OAPIType = GetAPIType<OArrayType>;
1184  static_assert(
1185  (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when swapping tuples.");
1186 
1188  other.size() == this->NumComps.value, "Cannot swap tuples with different sizes.");
1189 
1190  std::swap_ranges(this->begin(), this->end(), other.begin());
1191  }
1192 
1193  friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept { a.swap(b); }
1194 
1195  template <typename OArray, ComponentIdType OSize>
1197  {
1198  a.swap(b);
1199  }
1200 
1203  {
1204  return reference{ this->Array, this->NumComps, this->TupleId, i };
1205  }
1206 
1209  {
1210  // Let the reference type do the lookup during implicit conversion.
1211  return const_reference{ this->Array, this->NumComps, this->TupleId, i };
1212  }
1213 
1215  void fill(const value_type& v) noexcept { std::fill(this->begin(), this->end(), v); }
1216 
1218  size_type size() const noexcept { return this->NumComps.value; }
1219 
1221  iterator begin() noexcept { return this->NewIterator(0); }
1223  iterator end() noexcept { return this->NewIterator(this->NumComps.value); }
1224 
1226  const_iterator begin() const noexcept { return this->NewConstIterator(0); }
1228  const_iterator end() const noexcept { return this->NewConstIterator(this->NumComps.value); }
1229 
1231  const_iterator cbegin() const noexcept { return this->NewConstIterator(0); }
1233  const_iterator cend() const noexcept { return this->NewConstIterator(this->NumComps.value); }
1234 
1235  friend struct ConstTupleReference<ArrayType, TupleSize>;
1236  friend struct TupleIterator<ArrayType, TupleSize>;
1237 
1238 protected:
1240  iterator NewIterator(ComponentIdType comp) const noexcept
1241  {
1242  VTK_ITER_ASSUME(this->NumComps.value > 0);
1243  return iterator{ this->Array, this->NumComps, this->TupleId, comp };
1244  }
1245 
1248  {
1249  VTK_ITER_ASSUME(this->NumComps.value > 0);
1250  return const_iterator{ this->Array, this->NumComps, this->TupleId, comp };
1251  }
1252 
1254  void CopyReference(const TupleReference& o) noexcept
1255  {
1256  // Must use same array, other array types may use different implementations.
1257  VTK_ITER_ASSERT(this->Array == o.Array, "Cannot copy reference objects between arrays.");
1258  this->NumComps = o.NumComps;
1259  this->TupleId = o.TupleId;
1260  }
1261 
1262  mutable ArrayType* Array;
1265 };
1266 
1267 //------------------------------------------------------------------------------
1268 // Const tuple iterator
1269 template <typename ArrayType, ComponentIdType TupleSize>
1271 {
1272 private:
1273  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
1274  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
1275 
1277 
1278 public:
1279  using iterator_category = std::random_access_iterator_tag;
1284 
1286  ConstTupleIterator() noexcept = default;
1287 
1289  ConstTupleIterator(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
1290  : Ref(array, numComps, tupleId)
1291  {
1292  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
1293  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
1294  VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(),
1295  "Const tuple iterator at invalid tuple id.");
1296  }
1297 
1300  : Ref{ o.Ref }
1301  {
1302  }
1303 
1305  ConstTupleIterator(const ConstTupleIterator& o) noexcept = default;
1308  {
1309  this->Ref.CopyReference(o.Ref);
1310  return *this;
1311  }
1312 
1314  ConstTupleIterator& operator++() noexcept // prefix
1315  {
1316  ++this->Ref.TupleId;
1318  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1319  "Const tuple iterator at invalid component id.");
1320  return *this;
1321  }
1322 
1324  ConstTupleIterator operator++(int) noexcept // postfix
1325  {
1326  return ConstTupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId++ };
1327  }
1328 
1330  ConstTupleIterator& operator--() noexcept // prefix
1331  {
1332  --this->Ref.TupleId;
1334  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1335  "Const tuple iterator at invalid component id.");
1336  return *this;
1337  }
1338 
1340  ConstTupleIterator operator--(int) noexcept // postfix
1341  {
1342  return ConstTupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId-- };
1343  }
1344 
1347  {
1348  return reference{ this->GetArray(), this->GetNumComps(), this->GetTupleId() + i };
1349  }
1350 
1352  reference operator*() noexcept { return this->Ref; }
1353 
1355  pointer operator->() noexcept { return this->Ref; }
1356 
1357 #define VTK_TMP_MAKE_OPERATOR(OP) \
1358  friend VTK_ITER_INLINE bool operator OP( \
1359  const ConstTupleIterator& lhs, const ConstTupleIterator& rhs) noexcept \
1360  { \
1361  VTK_ITER_ASSERT( \
1362  lhs.GetArray() == rhs.GetArray(), "Cannot compare iterators from different arrays."); \
1363  VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \
1364  VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \
1365  return lhs.GetTupleId() OP rhs.GetTupleId(); \
1366  }
1367 
1374 
1375 #undef VTK_TMP_MAKE_OPERATOR
1376 
1379  {
1380  this->Ref.TupleId += offset;
1382  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1383  "Const tuple iterator at invalid component id.");
1384  return *this;
1385  }
1386 
1388  const ConstTupleIterator& it, difference_type offset) noexcept
1389  {
1390  return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1391  }
1392 
1394  difference_type offset, const ConstTupleIterator& it) noexcept
1395  {
1396  return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1397  }
1398 
1401  {
1402  this->Ref.TupleId -= offset;
1404  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1405  "Const tuple iterator at invalid component id.");
1406  return *this;
1407  }
1408 
1410  const ConstTupleIterator& it, difference_type offset) noexcept
1411  {
1412  return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() - offset };
1413  }
1414 
1416  const ConstTupleIterator& it1, const ConstTupleIterator& it2) noexcept
1417  {
1418  VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(),
1419  "Cannot do math with tuple iterators from different "
1420  "arrays.");
1421  return it1.GetTupleId() - it2.GetTupleId();
1422  }
1423 
1425  {
1426  // Different arrays may use different iterator implementations.
1428  lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays.");
1429 
1430  using std::swap;
1431  swap(lhs.GetTupleId(), rhs.GetTupleId());
1432  }
1433 
1434 private:
1436  ArrayType* GetArray() const noexcept { return this->Ref.Array; }
1438  ArrayType*& GetArray() noexcept { return this->Ref.Array; }
1440  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
1442  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
1444  TupleIdType GetTupleId() const noexcept { return this->Ref.TupleId; }
1446  TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; }
1447 
1448  ConstTupleReference<ArrayType, TupleSize> Ref;
1449 };
1450 
1451 //------------------------------------------------------------------------------
1452 // Tuple iterator
1453 template <typename ArrayType, ComponentIdType TupleSize>
1455 {
1456 private:
1457  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
1458  static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type.");
1459 
1461 
1462 public:
1463  using iterator_category = std::random_access_iterator_tag;
1468 
1470  TupleIterator() noexcept = default;
1471 
1473  TupleIterator(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept
1474  : Ref(array, numComps, tupleId)
1475  {
1476  VTK_ITER_ASSERT(array != nullptr, "Invalid array.");
1477  VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components.");
1479  tupleId >= 0 && tupleId <= array->GetNumberOfTuples(), "Tuple iterator at invalid tuple id.");
1480  }
1481 
1483  TupleIterator(const TupleIterator& o) noexcept = default;
1484 
1487  {
1488  this->Ref.CopyReference(o.Ref);
1489  return *this;
1490  }
1491 
1493  TupleIterator& operator++() noexcept // prefix
1494  {
1495  ++this->Ref.TupleId;
1497  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1498  "Tuple iterator at invalid component id.");
1499  return *this;
1500  }
1501 
1503  TupleIterator operator++(int) noexcept // postfix
1504  {
1505  return TupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId++ };
1506  }
1507 
1509  TupleIterator& operator--() noexcept // prefix
1510  {
1511  --this->Ref.TupleId;
1513  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1514  "Tuple iterator at invalid component id.");
1515  return *this;
1516  }
1517 
1519  TupleIterator operator--(int) noexcept // postfix
1520  {
1521  return TupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId-- };
1522  }
1523 
1526  {
1527  return reference{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId + i };
1528  }
1529 
1531  reference operator*() noexcept { return this->Ref; }
1532 
1534  pointer& operator->() noexcept { return this->Ref; }
1535 
1536 #define VTK_TMP_MAKE_OPERATOR(OP) \
1537  friend VTK_ITER_INLINE bool operator OP( \
1538  const TupleIterator& lhs, const TupleIterator& rhs) noexcept \
1539  { \
1540  VTK_ITER_ASSERT( \
1541  lhs.GetArray() == rhs.GetArray(), "Cannot compare iterators from different arrays."); \
1542  VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \
1543  VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \
1544  return lhs.GetTupleId() OP rhs.GetTupleId(); \
1545  }
1546 
1553 
1554 #undef VTK_TMP_MAKE_OPERATOR
1555 
1558  {
1559  this->Ref.TupleId += offset;
1561  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1562  "Tuple iterator at invalid component id.");
1563  return *this;
1564  }
1565 
1567  const TupleIterator& it, difference_type offset) noexcept
1568  {
1569  return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1570  }
1571 
1573  difference_type offset, const TupleIterator& it) noexcept
1574  {
1575  return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset };
1576  }
1577 
1580  {
1581  this->Ref.TupleId -= offset;
1583  this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(),
1584  "Tuple iterator at invalid component id.");
1585  return *this;
1586  }
1587 
1589  const TupleIterator& it, difference_type offset) noexcept
1590  {
1591  return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() - offset };
1592  }
1593 
1595  const TupleIterator& it1, const TupleIterator& it2) noexcept
1596  {
1597  VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(),
1598  "Cannot do math with tuple iterators from different "
1599  "arrays.");
1600  return it1.GetTupleId() - it2.GetTupleId();
1601  }
1602 
1603  friend VTK_ITER_INLINE void swap(TupleIterator& lhs, TupleIterator& rhs) noexcept
1604  {
1605  // Different arrays may use different iterator implementations.
1607  lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays.");
1608 
1609  using std::swap;
1610  swap(lhs.GetTupleId(), rhs.GetTupleId());
1611  }
1612 
1613  friend struct ConstTupleIterator<ArrayType, TupleSize>;
1614  friend struct ConstTupleReference<ArrayType, TupleSize>;
1615 
1616 protected:
1618  ArrayType* GetArray() const noexcept { return this->Ref.Array; }
1620  ArrayType*& GetArray() noexcept { return this->Ref.Array; }
1622  NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; }
1624  NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; }
1626  TupleIdType GetTupleId() const noexcept { return this->Ref.TupleId; }
1628  TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; }
1629 
1631 };
1632 
1633 //------------------------------------------------------------------------------
1634 // Tuple range
1635 template <typename ArrayTypeT, ComponentIdType TupleSize>
1637 {
1638 private:
1640  static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size.");
1641  static_assert(IsVtkDataArray<ArrayTypeT>::value, "Invalid array type.");
1642 
1643 public:
1644  using ArrayType = ArrayTypeT;
1655 
1656  // May be DynamicTupleSize, or the actual tuple size.
1657  constexpr static ComponentIdType TupleSizeTag = TupleSize;
1658 
1664 
1666  TupleRange() noexcept = default;
1667 
1669  TupleRange(ArrayType* arr, TupleIdType beginTuple, TupleIdType endTuple) noexcept
1670  : Array(arr)
1671  , NumComps(arr)
1672  , BeginTuple(beginTuple)
1673  , EndTuple(endTuple)
1674  {
1675  assert(this->Array);
1676  assert(beginTuple >= 0 && beginTuple <= endTuple);
1677  assert(endTuple >= 0 && endTuple <= this->Array->GetNumberOfTuples());
1678  }
1679 
1681  TupleRange GetSubRange(TupleIdType beginTuple = 0, TupleIdType endTuple = -1) const noexcept
1682  {
1683  const TupleIdType realBegin = this->BeginTuple + beginTuple;
1684  const TupleIdType realEnd = endTuple >= 0 ? this->BeginTuple + endTuple : this->EndTuple;
1685 
1686  return TupleRange{ this->Array, realBegin, realEnd };
1687  }
1688 
1690  ArrayType* GetArray() const noexcept { return this->Array; }
1692  ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; }
1694  TupleIdType GetBeginTupleId() const noexcept { return this->BeginTuple; }
1696  TupleIdType GetEndTupleId() const noexcept { return this->EndTuple; }
1697 
1699  size_type size() const noexcept { return this->EndTuple - this->BeginTuple; }
1700 
1702  iterator begin() noexcept { return this->NewIter(this->BeginTuple); }
1704  iterator end() noexcept { return this->NewIter(this->EndTuple); }
1705 
1707  const_iterator begin() const noexcept { return this->NewCIter(this->BeginTuple); }
1709  const_iterator end() const noexcept { return this->NewCIter(this->EndTuple); }
1710 
1712  const_iterator cbegin() const noexcept { return this->NewCIter(this->BeginTuple); }
1714  const_iterator cend() const noexcept { return this->NewCIter(this->EndTuple); }
1715 
1718  {
1719  return reference{ this->Array, this->NumComps, this->BeginTuple + i };
1720  }
1721 
1724  {
1725  return const_reference{ this->Array, this->NumComps, this->BeginTuple + i };
1726  }
1727 
1728 private:
1730  iterator NewIter(TupleIdType t) const { return iterator{ this->Array, this->NumComps, t }; }
1731 
1733  const_iterator NewCIter(TupleIdType t) const
1734  {
1735  return const_iterator{ this->Array, this->NumComps, t };
1736  }
1737 
1738  mutable ArrayType* Array{ nullptr };
1739  NumCompsType NumComps{};
1740  TupleIdType BeginTuple{ 0 };
1741  TupleIdType EndTuple{ 0 };
1742 };
1743 
1744 // Unimplemented, only used inside decltype in SelectTupleRange:
1745 template <typename ArrayType, ComponentIdType TupleSize>
1747 
1748 } // end namespace detail
1749 } // end namespace vtk
1750 
1752 
1753 #endif // __VTK_WRAP__
1754 #endif // vtkDataArrayTupleRange_Generic_h
1755 
1756 // VTK-HeaderTest-Exclude: vtkDataArrayTupleRange_Generic.h
abstract superclass for arrays of numeric data
Definition: vtkDataArray.h:50
@ value
Definition: vtkX3D.h:226
@ offset
Definition: vtkX3D.h:444
typename std::enable_if< AreStaticTupleSizes< S1, S2 >::value, T >::type EnableIfStaticTupleSizes
TupleRange< AOSArrayType, TupleSize > DeclareTupleRangeSpecialization(ArrayType *)
typename std::enable_if< IsEitherTupleSizeDynamic< S1, S2 >::value, T >::type EnableIfEitherTupleSizeIsDynamic
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
typename detail::GetAPITypeImpl< ArrayType >::APIType GetAPIType
vtkIdType TupleIdType
int ComponentIdType
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 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 TupleReference * operator->() 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 TupleReference(TupleReference &&)=default
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)