VTK  9.3.20240416
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>
21 struct CollectionRange;
22 template <typename CollectionType>
23 struct CollectionIterator;
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>
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 
104  : Element(nullptr)
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 elem = this->Element;
120  this->Increment();
121  return CollectionIterator{ elem };
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.Element == rhs.Element;
131  }
132 
133  friend bool operator!=(const CollectionIterator& lhs, const CollectionIterator& rhs) noexcept
134  {
135  return lhs.Element != rhs.Element;
136  }
137 
138  friend void swap(CollectionIterator& lhs, CollectionIterator& rhs) noexcept
139  {
140  using std::swap;
141  swap(lhs.Element, rhs.Element);
142  }
143 
144  friend struct CollectionRange<CollectionType>;
145 
146 protected:
148  : Element(element)
149  {
150  }
151 
152 private:
153  void Increment() noexcept
154  { // incrementing an invalid iterator is UB, no need to check for non-null.
155  this->Element = this->Element->Next;
156  }
157 
158  ItemType* GetItem() const noexcept { return static_cast<ItemType*>(this->Element->Item); }
159 
160  vtkCollectionElement* Element;
161 };
162 
163 //------------------------------------------------------------------------------
164 // Collection range proxy.
165 // The const_iterators/references are the same as the non-const versions, since
166 // vtkObjects marked const are unusable.
167 template <typename CollectionType>
169 {
170  static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
171 
173 
174  // NOTE: The const items are the same as the mutable ones, since const
175  // vtkObjects are generally unusable.
176  using size_type = int; // int is used by the vtkCollection API.
179  using reference = ItemType*;
182 
183  CollectionRange(CollectionType* coll) noexcept
184  : Collection(coll)
185  {
186  assert(this->Collection);
187  }
188 
189  CollectionType* GetCollection() const noexcept { return this->Collection; }
190 
191  size_type size() const noexcept { return this->Collection->GetNumberOfItems(); }
192 
193  iterator begin() const
194  {
196  this->Collection->InitTraversal(cookie);
197  // The cookie is a linked list node pointer, vtkCollectionElement:
198  return iterator{ static_cast<vtkCollectionElement*>(cookie) };
199  }
200 
201  iterator end() const { return iterator{ nullptr }; }
202 
203  // Note: These return mutable objects because const vtkObject are unusable.
205  {
207  this->Collection->InitTraversal(cookie);
208  // The cookie is a linked list node pointer, vtkCollectionElement:
209  return const_iterator{ static_cast<vtkCollectionElement*>(cookie) };
210  }
211 
212  // Note: These return mutable objects because const vtkObjects are unusable.
213  const_iterator cend() const { return const_iterator{ nullptr }; }
214 
215 private:
217 };
218 
219 VTK_ABI_NAMESPACE_END
220 }
221 } // end namespace vtk::detail
222 
223 #endif // vtkCollectionRange_h
224 
225 // VTK-HeaderTest-Exclude: vtkCollectionRange.h
vtkCollectionElement * Next
Definition: vtkCollection.h:39
@ value
Definition: vtkX3D.h:220
@ type
Definition: vtkX3D.h:516
typename std::enable_if< IsCollection< CollectionType >::value, T >::type EnableIfIsCollection
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
CollectionIterator operator++(int) noexcept
std::forward_iterator_tag iterator_category
typename GetCollectionItemType< CollectionType >::Type * pointer
reference operator*() const noexcept
CollectionIterator & operator=(const CollectionIterator &o) noexcept=default
CollectionIterator & operator++() noexcept
CollectionIterator(vtkCollectionElement *element) noexcept
friend void swap(CollectionIterator &lhs, CollectionIterator &rhs) noexcept
typename GetCollectionItemType< CollectionType >::Type * reference
pointer operator->() const noexcept
CollectionIterator(const CollectionIterator &o) noexcept=default
friend bool operator==(const CollectionIterator &lhs, const CollectionIterator &rhs) noexcept
typename GetCollectionItemType< CollectionType >::Type * value_type
friend bool operator!=(const CollectionIterator &lhs, const CollectionIterator &rhs) noexcept
CollectionRange(CollectionType *coll) noexcept
CollectionType * GetCollection() const noexcept
typename GetCollectionItemType< CollectionType >::Type ItemType
size_type size() const noexcept
const_iterator cbegin() const
const_iterator cend() const
typename std::remove_pointer< PointerType >::type Type
void * vtkCollectionSimpleIterator
Definition: vtkCollection.h:41
This file contains a variety of metaprogramming constructs for working with vtk types.