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