VTK  9.2.6
vtkCollectionRange.h
Go to the documentation of this file.
1/*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkCollectionRange.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=========================================================================*/
15
16#ifndef vtkCollectionRange_h
17#define vtkCollectionRange_h
18
19#include "vtkCollection.h"
20#include "vtkMeta.h"
21#include "vtkRange.h"
22#include "vtkSmartPointer.h"
23
24#include <cassert>
25
26namespace vtk
27{
28namespace detail
29{
30
31template <typename CollectionType>
32struct CollectionRange;
33template <typename CollectionType>
35
36//------------------------------------------------------------------------------
37// Detect vtkCollection types
38template <typename T>
39struct IsCollection : std::is_base_of<vtkCollection, T>
40{
41};
42
43template <typename CollectionType, typename T = CollectionType>
44using EnableIfIsCollection = typename std::enable_if<IsCollection<CollectionType>::value, T>::type;
45
46//------------------------------------------------------------------------------
47// Detect the type of items held by the collection by checking the return type
48// of GetNextItem(), or GetNextItemAsObject() as a fallback.
49template <typename CollectionType>
51{
52 static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
53
54private:
55 // The GetType methods are only used in a decltype context and are left
56 // unimplemented as we only care about their signatures. They are used to
57 // determine the type of object held by the collection.
58 //
59 // By passing literal 0 as the argument, the overload taking `int` is
60 // preferred and returns the same type as CollectionType::GetNextItem, which
61 // is usually the exact type held by the collection (e.g.
62 // vtkRendererCollection::GetNextItem returns vtkRenderer*).
63 //
64 // If the collection class does not define GetNextItem, SFINAE removes the
65 // preferred `int` overload, and the `...` overload is used instead. This
66 // method returns the same type as vtkCollection::GetNextItemAsObject, which
67 // is vtkObject*. This lets us define a more derived collection item type
68 // when possible, while falling back to the general vtkObject if a more
69 // refined type is not known.
70
71 // not implemented
72 template <typename T>
73 static auto GetType(...) -> decltype(std::declval<T>().GetNextItemAsObject());
74
75 // not implemented
76 template <typename T>
77 static auto GetType(int) -> decltype(std::declval<T>().GetNextItem());
78
79 using PointerType = decltype(GetType<CollectionType>(0));
80
81public:
82 // Just use std::remove pointer, vtk::detail::StripPointer is overkill.
83 using Type = typename std::remove_pointer<PointerType>::type;
84};
85
86//------------------------------------------------------------------------------
87// Collection iterator. Reference, value, and pointer types are all ItemType
88// pointers, since:
89// a) values: ItemType* instead of ItemType because vtkObjects can't be
90// copied/assigned.
91// b) references: No good usecase to change the pointers held by the collection
92// by returning ItemType*&, nor would returning ItemType& be useful, since
93// it'd have to be dereferenced anyway to pass it anywhere, and vtkObjects
94// are conventionally held by address.
95// c) pointers: Returning ItemType** from operator-> would be useless.
96//
97// There are no const_reference, etc, since VTK is not const correct and marking
98// vtkObjects consts makes them unusable.
99template <typename CollectionType>
101 : public std::iterator<std::forward_iterator_tag,
102 typename GetCollectionItemType<CollectionType>::Type*, int,
103 typename GetCollectionItemType<CollectionType>::Type*,
104 typename GetCollectionItemType<CollectionType>::Type*>
105{
106 static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
107
108private:
109 using ItemType = typename GetCollectionItemType<CollectionType>::Type;
110 using Superclass = std::iterator<std::forward_iterator_tag, ItemType*, int, ItemType*, ItemType*>;
111
112public:
113 using iterator_category = typename Superclass::iterator_category;
114 using value_type = typename Superclass::value_type;
115 using difference_type = typename Superclass::difference_type;
116 using pointer = typename Superclass::pointer;
117 using reference = typename Superclass::reference;
118
120 : Element(nullptr)
121 {
122 }
123
124 CollectionIterator(const CollectionIterator& o) noexcept = default;
125 CollectionIterator& operator=(const CollectionIterator& o) noexcept = default;
126
127 CollectionIterator& operator++() noexcept // prefix
128 {
129 this->Increment();
130 return *this;
131 }
132
133 CollectionIterator operator++(int) noexcept // postfix
134 {
135 auto elem = this->Element;
136 this->Increment();
137 return CollectionIterator{ elem };
138 }
139
140 reference operator*() const noexcept { return this->GetItem(); }
141
142 pointer operator->() const noexcept { return this->GetItem(); }
143
144 friend bool operator==(const CollectionIterator& lhs, const CollectionIterator& rhs) noexcept
145 {
146 return lhs.Element == rhs.Element;
147 }
148
149 friend bool operator!=(const CollectionIterator& lhs, const CollectionIterator& rhs) noexcept
150 {
151 return lhs.Element != rhs.Element;
152 }
153
154 friend void swap(CollectionIterator& lhs, CollectionIterator& rhs) noexcept
155 {
156 using std::swap;
157 swap(lhs.Element, rhs.Element);
158 }
159
160 friend struct CollectionRange<CollectionType>;
161
162protected:
164 : Element(element)
165 {
166 }
167
168private:
169 void Increment() noexcept
170 { // incrementing an invalid iterator is UB, no need to check for non-null.
171 this->Element = this->Element->Next;
172 }
173
174 ItemType* GetItem() const noexcept { return static_cast<ItemType*>(this->Element->Item); }
175
176 vtkCollectionElement* Element;
177};
178
179//------------------------------------------------------------------------------
180// Collection range proxy.
181// The const_iterators/references are the same as the non-const versions, since
182// vtkObjects marked const are unusable.
183template <typename CollectionType>
185{
186 static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
187
189
190 // NOTE: The const items are the same as the mutable ones, since const
191 // vtkObjects are generally unusable.
192 using size_type = int; // int is used by the vtkCollection API.
198
199 CollectionRange(CollectionType* coll) noexcept
200 : Collection(coll)
201 {
202 assert(this->Collection);
203 }
204
205 CollectionType* GetCollection() const noexcept { return this->Collection; }
206
207 size_type size() const noexcept { return this->Collection->GetNumberOfItems(); }
208
210 {
212 this->Collection->InitTraversal(cookie);
213 // The cookie is a linked list node pointer, vtkCollectionElement:
214 return iterator{ static_cast<vtkCollectionElement*>(cookie) };
215 }
216
217 iterator end() const { return iterator{ nullptr }; }
218
219 // Note: These return mutable objects because const vtkObject are unusable.
221 {
223 this->Collection->InitTraversal(cookie);
224 // The cookie is a linked list node pointer, vtkCollectionElement:
225 return const_iterator{ static_cast<vtkCollectionElement*>(cookie) };
226 }
227
228 // Note: These return mutable objects because const vtkObjects are unusable.
229 const_iterator cend() const { return const_iterator{ nullptr }; }
230
231private:
233};
234
235}
236} // end namespace vtk::detail
237
238#endif // vtkCollectionRange_h
239
240// 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
typename Superclass::value_type value_type
reference operator*() const noexcept
CollectionIterator & operator++() noexcept
typename Superclass::reference reference
CollectionIterator & operator=(const CollectionIterator &o) noexcept=default
typename Superclass::difference_type difference_type
typename Superclass::pointer pointer
typename Superclass::iterator_category iterator_category
CollectionIterator(vtkCollectionElement *element) noexcept
friend void swap(CollectionIterator &lhs, CollectionIterator &rhs) noexcept
pointer operator->() const noexcept
CollectionIterator(const CollectionIterator &o) noexcept=default
friend bool operator==(const CollectionIterator &lhs, const CollectionIterator &rhs) noexcept
friend bool operator!=(const CollectionIterator &lhs, const CollectionIterator &rhs) noexcept
CollectionRange(CollectionType *coll) noexcept
CollectionType * GetCollection() const noexcept
CollectionIterator< CollectionType > const_iterator
typename GetCollectionItemType< CollectionType >::Type ItemType
size_type size() const noexcept
CollectionIterator< CollectionType > iterator
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.