VTK  9.4.20250130
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
14namespace vtk
15{
16namespace detail
17{
18VTK_ABI_NAMESPACE_BEGIN
19
20template <typename CollectionType>
21struct CollectionRange;
22template <typename CollectionType>
23struct CollectionIterator;
24
25//------------------------------------------------------------------------------
26// Detect vtkCollection types
27template <typename T>
28struct IsCollection : std::is_base_of<vtkCollection, T>
29{
30};
31
32template <typename CollectionType, typename T = CollectionType>
33using 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.
38template <typename CollectionType>
40{
41 static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
42
43private:
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
70public:
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.
88template <typename CollectionType>
90{
91 static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
92
93private:
94 using ItemType = typename GetCollectionItemType<CollectionType>::Type;
95
96public:
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
146protected:
148 : Element(element)
149 {
150 }
151
152private:
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.
167template <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.
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
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
215private:
217};
218
219VTK_ABI_NAMESPACE_END
220}
221} // end namespace vtk::detail
222
223#endif // vtkCollectionRange_h
224
225// VTK-HeaderTest-Exclude: vtkCollectionRange.h
vtkCollectionElement * Next
Hold a reference to a vtkObjectBase instance.
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++() noexcept
CollectionIterator & operator=(const CollectionIterator &o) noexcept=default
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
typename std::remove_pointer< PointerType >::type Type
void * vtkCollectionSimpleIterator
This file contains a variety of metaprogramming constructs for working with vtk types.