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