VTK: Common/Core/vtkCollectionRange.h Source File

| VTK 9.3.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>
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>
33 using EnableIfIsCollection = typename std::enable_if<IsCollection<CollectionType>::value, T>::type;
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>
39 struct GetCollectionItemType
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.
72 using Type = typename std::remove_pointer<PointerType>::type;
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;
98 using value_type = typename GetCollectionItemType<CollectionType>::Type*;
99 using difference_type = int;
100 using pointer = typename GetCollectionItemType<CollectionType>::Type*;
101 using reference = typename GetCollectionItemType<CollectionType>::Type*;
102
103 CollectionIterator() noexcept
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:
147 CollectionIterator(vtkCollectionElement* element) noexcept
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>
168 struct CollectionRange
169 {
170 static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
171
172 using ItemType = typename GetCollectionItemType<CollectionType>::Type;
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.
177 using iterator = CollectionIterator<CollectionType>;
178 using const_iterator = CollectionIterator<CollectionType>;
179 using reference = ItemType*;
180 using const_reference = ItemType*;
181 using value_type = 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 {
195 vtkCollectionSimpleIterator cookie;
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.
204 const_iterator cbegin() const
205 {
206 vtkCollectionSimpleIterator cookie;
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:
216 vtkSmartPointer<CollectionType> Collection;
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
Definition: vtkCollection.h:30
vtkCollectionElement::Next
vtkCollectionElement * Next
Definition: vtkCollection.h:38
vtkCollectionElement::Item
vtkObject * Item
Definition: vtkCollection.h:37
vtkSmartPointer< CollectionType >
detail
Definition: vtkCellTreeLocator.h:59
vtkX3D::value
@ value
Definition: vtkX3D.h:220
vtkX3D::type
@ type
Definition: vtkX3D.h:516
vtk::detail::EnableIfIsCollection
typename std::enable_if< IsCollection< CollectionType >::value, T >::type EnableIfIsCollection
Definition: vtkCollectionRange.h:33
vtk
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
Definition: vtkSMPThreadLocalAPI.h:30
vtk::detail::CollectionIterator
Definition: vtkCollectionRange.h:90
vtk::detail::CollectionIterator::operator++
CollectionIterator operator++(int) noexcept
Definition: vtkCollectionRange.h:117
vtk::detail::CollectionIterator::iterator_category
std::forward_iterator_tag iterator_category
Definition: vtkCollectionRange.h:97
vtk::detail::CollectionIterator::pointer
typename GetCollectionItemType< CollectionType >::Type * pointer
Definition: vtkCollectionRange.h:100
vtk::detail::CollectionIterator::operator*
reference operator*() const noexcept
Definition: vtkCollectionRange.h:124
vtk::detail::CollectionIterator::operator=
CollectionIterator & operator=(const CollectionIterator &o) noexcept=default
vtk::detail::CollectionIterator::difference_type
int difference_type
Definition: vtkCollectionRange.h:99
vtk::detail::CollectionIterator::CollectionIterator
CollectionIterator() noexcept
Definition: vtkCollectionRange.h:103
vtk::detail::CollectionIterator::operator++
CollectionIterator & operator++() noexcept
Definition: vtkCollectionRange.h:111
vtk::detail::CollectionIterator::CollectionIterator
CollectionIterator(vtkCollectionElement *element) noexcept
Definition: vtkCollectionRange.h:147
vtk::detail::CollectionIterator::swap
friend void swap(CollectionIterator &lhs, CollectionIterator &rhs) noexcept
Definition: vtkCollectionRange.h:138
vtk::detail::CollectionIterator::reference
typename GetCollectionItemType< CollectionType >::Type * reference
Definition: vtkCollectionRange.h:101
vtk::detail::CollectionIterator::operator->
pointer operator->() const noexcept
Definition: vtkCollectionRange.h:126
vtk::detail::CollectionIterator::CollectionIterator
CollectionIterator(const CollectionIterator &o) noexcept=default
vtk::detail::CollectionIterator::operator==
friend bool operator==(const CollectionIterator &lhs, const CollectionIterator &rhs) noexcept
Definition: vtkCollectionRange.h:128
vtk::detail::CollectionIterator::value_type
typename GetCollectionItemType< CollectionType >::Type * value_type
Definition: vtkCollectionRange.h:98
vtk::detail::CollectionIterator::operator!=
friend bool operator!=(const CollectionIterator &lhs, const CollectionIterator &rhs) noexcept
Definition: vtkCollectionRange.h:133
vtk::detail::CollectionRange
Definition: vtkCollectionRange.h:169
vtk::detail::CollectionRange::reference
ItemType * reference
Definition: vtkCollectionRange.h:179
vtk::detail::CollectionRange::value_type
ItemType * value_type
Definition: vtkCollectionRange.h:181
vtk::detail::CollectionRange::CollectionRange
CollectionRange(CollectionType *coll) noexcept
Definition: vtkCollectionRange.h:183
vtk::detail::CollectionRange::begin
iterator begin() const
Definition: vtkCollectionRange.h:193
vtk::detail::CollectionRange::GetCollection
CollectionType * GetCollection() const noexcept
Definition: vtkCollectionRange.h:189
vtk::detail::CollectionRange::const_reference
ItemType * const_reference
Definition: vtkCollectionRange.h:180
vtk::detail::CollectionRange::end
iterator end() const
Definition: vtkCollectionRange.h:201
vtk::detail::CollectionRange::size_type
int size_type
Definition: vtkCollectionRange.h:176
vtk::detail::CollectionRange::ItemType
typename GetCollectionItemType< CollectionType >::Type ItemType
Definition: vtkCollectionRange.h:172
vtk::detail::CollectionRange::size
size_type size() const noexcept
Definition: vtkCollectionRange.h:191
vtk::detail::CollectionRange::cbegin
const_iterator cbegin() const
Definition: vtkCollectionRange.h:204
vtk::detail::CollectionRange::cend
const_iterator cend() const
Definition: vtkCollectionRange.h:213
vtk::detail::GetCollectionItemType
Definition: vtkCollectionRange.h:40
vtk::detail::GetCollectionItemType::Type
typename std::remove_pointer< PointerType >::type Type
Definition: vtkCollectionRange.h:72
vtk::detail::IsCollection
Definition: vtkCollectionRange.h:29
vtkCollection.h
vtkCollectionSimpleIterator
void * vtkCollectionSimpleIterator
Definition: vtkCollection.h:40
vtkMeta.h
This file contains a variety of metaprogramming constructs for working with vtk types.
vtkRange.h
vtkSmartPointer.h