VTK  9.7.1
vtkCollectionRange.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
3 
4 #ifndef vtkCollectionRange_h
5 #define vtkCollectionRange_h
6 
7 #include "vtkCollection.h"
8 #include "vtkMeta.h"
9 #include "vtkRange.h"
10 #include "vtkSmartPointer.h"
11 
12 #include <cassert>
13 
14 namespace vtk
15 {
16 namespace detail
17 {
18 VTK_ABI_NAMESPACE_BEGIN
19 
20 template <typename CollectionType>
22 template <typename CollectionType>
24 
25 //------------------------------------------------------------------------------
26 // Detect vtkCollection types
27 template <typename T>
28 struct IsCollection : std::is_base_of<vtkCollection, T>
29 {
30 };
31 
32 template <typename CollectionType, typename T = CollectionType>
34 
35 //------------------------------------------------------------------------------
36 // Detect the type of items held by the collection by checking the return type
37 // of GetNextItem(), or GetNextItemAsObject() as a fallback.
38 template <typename CollectionType>
40 {
41  static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
42 
43 private:
44  // The GetType methods are only used in a decltype context and are left
45  // unimplemented as we only care about their signatures. They are used to
46  // determine the type of object held by the collection.
47  //
48  // By passing literal 0 as the argument, the overload taking `int` is
49  // preferred and returns the same type as CollectionType::GetNextItem, which
50  // is usually the exact type held by the collection (e.g.
51  // vtkRendererCollection::GetNextItem returns vtkRenderer*).
52  //
53  // If the collection class does not define GetNextItem, SFINAE removes the
54  // preferred `int` overload, and the `...` overload is used instead. This
55  // method returns the same type as vtkCollection::GetNextItemAsObject, which
56  // is vtkObject*. This lets us define a more derived collection item type
57  // when possible, while falling back to the general vtkObject if a more
58  // refined type is not known.
59 
60  // not implemented
61  template <typename T>
62  static auto GetType(...) -> decltype(std::declval<T>().GetNextItemAsObject());
63 
64  // not implemented
65  template <typename T>
66  static auto GetType(int) -> decltype(std::declval<T>().GetNextItem());
67 
68  using PointerType = decltype(GetType<CollectionType>(0));
69 
70 public:
71  // Just use std::remove pointer, vtk::detail::StripPointer is overkill.
73 };
74 
75 //------------------------------------------------------------------------------
76 // Collection iterator. Reference, value, and pointer types are all ItemType
77 // pointers, since:
78 // a) values: ItemType* instead of ItemType because vtkObjects can't be
79 // copied/assigned.
80 // b) references: No good usecase to change the pointers held by the collection
81 // by returning ItemType*&, nor would returning ItemType& be useful, since
82 // it'd have to be dereferenced anyway to pass it anywhere, and vtkObjects
83 // are conventionally held by address.
84 // c) pointers: Returning ItemType** from operator-> would be useless.
85 //
86 // There are no const_reference, etc, since VTK is not const correct and marking
87 // vtkObjects consts makes them unusable.
88 template <typename CollectionType>
89 struct CollectionIterator
90 {
91  static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
92 
93 private:
94  using ItemType = typename GetCollectionItemType<CollectionType>::Type;
95 
96 public:
97  using iterator_category = std::forward_iterator_tag;
99  using difference_type = int;
102 
103  CollectionIterator(std::vector<vtkObject*>::iterator iterator) noexcept
104  : Iterator(iterator)
105  {
106  }
107 
108  CollectionIterator(const CollectionIterator& o) noexcept = default;
109  CollectionIterator& operator=(const CollectionIterator& o) noexcept = default;
110 
111  CollectionIterator& operator++() noexcept // prefix
112  {
113  this->Increment();
114  return *this;
115  }
116 
117  CollectionIterator operator++(int) noexcept // postfix
118  {
119  auto it = this->Iterator;
120  this->Increment();
121  return CollectionIterator{ it };
122  }
123 
124  reference operator*() const noexcept { return this->GetItem(); }
125 
126  pointer operator->() const noexcept { return this->GetItem(); }
127 
128  friend bool operator==(const CollectionIterator& lhs, const CollectionIterator& rhs) noexcept
129  {
130  return lhs.Iterator == rhs.Iterator;
131  }
132 
133  friend bool operator!=(const CollectionIterator& lhs, const CollectionIterator& rhs) noexcept
134  {
135  return lhs.Iterator != rhs.Iterator;
136  }
137 
138  friend void swap(CollectionIterator& lhs, CollectionIterator& rhs) noexcept
139  {
140  using std::swap;
141  swap(lhs.Iterator, rhs.Iterator);
142  }
143 
144  friend struct CollectionRange<CollectionType>;
145 
146 protected:
147 private:
148  void Increment() noexcept
149  { // incrementing an invalid iterator is UB, no need to check for non-null.
150  this->Iterator++;
151  }
152 
153  ItemType* GetItem() const noexcept { return static_cast<ItemType*>(*this->Iterator); }
154 
155  std::vector<vtkObject*>::iterator Iterator;
156 };
157 
158 //------------------------------------------------------------------------------
159 // Collection range proxy.
160 // The const_iterators/references are the same as the non-const versions, since
161 // vtkObjects marked const are unusable.
162 template <typename CollectionType>
163 struct CollectionRange
164 {
165  static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
166 
168 
169  // NOTE: The const items are the same as the mutable ones, since const
170  // vtkObjects are generally unusable.
171  using size_type = int; // int is used by the vtkCollection API.
174  using reference = ItemType*;
177 
178  CollectionRange(CollectionType* coll) noexcept
179  : Collection(coll)
180  {
181  assert(this->Collection);
182  }
183 
184  CollectionType* GetCollection() const noexcept { return this->Collection; }
185 
186  size_type size() const noexcept { return this->Collection->GetNumberOfItems(); }
187 
188  iterator begin() const { return iterator{ this->Collection->begin() }; }
189 
190  iterator end() const { return iterator{ this->Collection->end() }; }
191 
192  // Note: These return mutable objects because const vtkObject are unusable.
193  const_iterator cbegin() const { return const_iterator{ this->Collection->begin() }; }
194 
195  // Note: These return mutable objects because const vtkObjects are unusable.
196  const_iterator cend() const { return const_iterator{ this->Collection->end() }; }
197 
198 private:
200 };
201 
202 VTK_ABI_NAMESPACE_END
203 }
204 } // end namespace vtk::detail
205 
206 #endif // vtkCollectionRange_h
207 
208 // VTK-HeaderTest-Exclude: vtkCollectionRange.h
typename std::remove_pointer< PointerType >::type Type
typename std::enable_if< IsCollection< CollectionType >::value, T >::type EnableIfIsCollection
size_type size() const noexcept
typename GetCollectionItemType< CollectionType >::Type * reference
friend void swap(CollectionIterator &lhs, CollectionIterator &rhs) noexcept
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
CollectionIterator & operator++() noexcept
pointer operator->() const noexcept
This file contains a variety of metaprogramming constructs for working with vtk types.
typename GetCollectionItemType< CollectionType >::Type * pointer
CollectionIterator(std::vector< vtkObject * >::iterator iterator) noexcept
friend bool operator!=(const CollectionIterator &lhs, const CollectionIterator &rhs) noexcept
const_iterator cend() const
CollectionIterator operator++(int) noexcept
CollectionIterator & operator=(const CollectionIterator &o) noexcept=default
typename GetCollectionItemType< CollectionType >::Type ItemType
std::forward_iterator_tag iterator_category
const_iterator cbegin() const
CollectionRange(CollectionType *coll) noexcept
typename GetCollectionItemType< CollectionType >::Type * value_type
friend bool operator==(const CollectionIterator &lhs, const CollectionIterator &rhs) noexcept
reference operator*() const noexcept
CollectionType * GetCollection() const noexcept