VTK
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 "vtkSmartPointer.h"
24 #include "vtkRange.h"
25 
26 #include <cassert>
27 
28 namespace vtk
29 {
30 namespace detail
31 {
32 
33 template <typename CollectionType> struct CollectionRange;
34 template <typename CollectionType> struct CollectionIterator;
35 
36 //------------------------------------------------------------------------------
37 // Detect vtkCollection types
38 template <typename T>
39 struct IsCollection : std::is_base_of<vtkCollection, T> {};
40 
41 template <typename CollectionType, typename T = CollectionType>
44 
45 //------------------------------------------------------------------------------
46 // Detect the type of items held by the collection by checking the return type
47 // of GetNextItem(), or GetNextItemAsObject() as a fallback.
48 template <typename CollectionType>
50 {
52  "Invalid vtkCollection subclass.");
53 private:
54 
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(...)
74  -> decltype(std::declval<T>().GetNextItemAsObject());
75 
76  // not implemented
77  template <typename T>
78  static auto GetType(int)
79  -> decltype(std::declval<T>().GetNextItem());
80 
81  using PointerType = decltype(GetType<CollectionType>(0));
82 
83 public:
84  // Just use std::remove pointer, vtk::detail::StripPointer is overkill.
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.
101 template <typename CollectionType>
102 struct CollectionIterator :
103  public std::iterator<std::forward_iterator_tag,
104  typename GetCollectionItemType<CollectionType>::Type*,
105  int,
106  typename GetCollectionItemType<CollectionType>::Type*,
107  typename GetCollectionItemType<CollectionType>::Type*>
108 {
110  "Invalid vtkCollection subclass.");
111 private:
112  using ItemType = typename GetCollectionItemType<CollectionType>::Type;
113  using Superclass = std::iterator<std::forward_iterator_tag,
114  ItemType*,
115  int,
116  ItemType*,
117  ItemType*>;
118 
119 public:
120  using iterator_category = typename Superclass::iterator_category;
121  using value_type = typename Superclass::value_type;
122  using difference_type = typename Superclass::difference_type;
123  using pointer = typename Superclass::pointer;
125 
126  CollectionIterator() noexcept : Element(nullptr) {}
127 
128  CollectionIterator(const CollectionIterator& o) noexcept = default;
129  CollectionIterator& operator=(const CollectionIterator& o) noexcept = default;
130 
131  CollectionIterator& operator++() noexcept // prefix
132  {
133  this->Increment();
134  return *this;
135  }
136 
137  CollectionIterator operator++(int) noexcept // postfix
138  {
139  auto elem = this->Element;
140  this->Increment();
141  return CollectionIterator{elem};
142  }
143 
144  reference operator*() const noexcept
145  {
146  return this->GetItem();
147  }
148 
149  pointer operator->() const noexcept
150  {
151  return this->GetItem();
152  }
153 
154  friend bool operator==(const CollectionIterator& lhs,
155  const CollectionIterator& rhs) noexcept
156  {
157  return lhs.Element == rhs.Element;
158  }
159 
160  friend bool operator!=(const CollectionIterator& lhs,
161  const CollectionIterator& rhs) noexcept
162  {
163  return lhs.Element != rhs.Element;
164  }
165 
166  friend void swap(CollectionIterator& lhs, CollectionIterator &rhs) noexcept
167  {
168  using std::swap;
169  swap(lhs.Element, rhs.Element);
170  }
171 
172  friend struct CollectionRange<CollectionType>;
173 
174 protected:
176  : Element(element)
177  {
178  }
179 
180 private:
181  void Increment() noexcept
182  { // incrementing an invalid iterator is UB, no need to check for non-null.
183  this->Element = this->Element->Next;
184  }
185 
186  ItemType* GetItem() const noexcept
187  {
188  return static_cast<ItemType*>(this->Element->Item);
189  }
190 
191  vtkCollectionElement *Element;
192 };
193 
194 //------------------------------------------------------------------------------
195 // Collection range proxy.
196 // The const_iterators/references are the same as the non-const versions, since
197 // vtkObjects marked const are unusable.
198 template <typename CollectionType>
199 struct CollectionRange
200 {
202  "Invalid vtkCollection subclass.");
203 
205 
206  // NOTE: The const items are the same as the mutable ones, since const
207  // vtkObjects are generally unusable.
208  using size_type = int; // int is used by the vtkCollection API.
211  using reference = ItemType*;
214 
215  CollectionRange(CollectionType *coll) noexcept
216  : Collection(coll)
217  {
218  assert(this->Collection);
219  }
220 
221  CollectionType* GetCollection() const noexcept { return this->Collection; }
222 
223  size_type size() const noexcept
224  {
225  return this->Collection->GetNumberOfItems();
226  }
227 
228  iterator begin() const
229  {
231  this->Collection->InitTraversal(cookie);
232  // The cookie is a linked list node pointer, vtkCollectionElement:
233  return iterator{static_cast<vtkCollectionElement*>(cookie)};
234  }
235 
236  iterator end() const
237  {
238  return iterator{nullptr};
239  }
240 
241  // Note: These return mutable objects because const vtkObject are unusable.
243  {
245  this->Collection->InitTraversal(cookie);
246  // The cookie is a linked list node pointer, vtkCollectionElement:
247  return const_iterator{static_cast<vtkCollectionElement*>(cookie)};
248  }
249 
250  // Note: These return mutable objects because const vtkObjects are unusable.
252  {
253  return const_iterator{nullptr};
254  }
255 
256 private:
258 };
259 
260 }
261 } // end namespace vtk::detail
262 
263 #endif // __VTK_WRAP__
264 
265 #endif // vtkCollectionRange_h
266 
267 // VTK-HeaderTest-Exclude: vtkCollectionRange.h
typename std::remove_pointer< PointerType >::type Type
void * vtkCollectionSimpleIterator
Definition: vtkCollection.h:47
typename std::enable_if< IsCollection< CollectionType >::value, T >::type EnableIfIsCollection
typename Superclass::difference_type difference_type
friend void swap(CollectionIterator &lhs, CollectionIterator &rhs) noexcept
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
CollectionIterator & operator++() noexcept
typename Superclass::pointer pointer
pointer operator->() const noexcept
friend bool operator!=(const CollectionIterator &lhs, const CollectionIterator &rhs) noexcept
size_type size() const noexcept
const_iterator cend() const
typename Superclass::iterator_category iterator_category
CollectionIterator operator++(int) noexcept
CollectionIterator(vtkCollectionElement *element) noexcept
typename GetCollectionItemType< CollectionType >::Type ItemType
reference operator*() const noexcept
const_iterator cbegin() const
CollectionType * GetCollection() const noexcept
CollectionRange(CollectionType *coll) noexcept
typename Superclass::reference reference
friend bool operator==(const CollectionIterator &lhs, const CollectionIterator &rhs) noexcept
typename Superclass::value_type value_type