VTK  9.2.20220705
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 
26 namespace vtk
27 {
28 namespace detail
29 {
30 
31 template <typename CollectionType>
32 struct CollectionRange;
33 template <typename CollectionType>
34 struct CollectionIterator;
35 
36 //------------------------------------------------------------------------------
37 // Detect vtkCollection types
38 template <typename T>
39 struct IsCollection : std::is_base_of<vtkCollection, T>
40 {
41 };
42 
43 template <typename CollectionType, typename T = CollectionType>
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.
49 template <typename CollectionType>
51 {
52  static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
53 
54 private:
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 
81 public:
82  // Just use std::remove pointer, vtk::detail::StripPointer is overkill.
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.
99 template <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 
108 private:
109  using ItemType = typename GetCollectionItemType<CollectionType>::Type;
110  using Superclass = std::iterator<std::forward_iterator_tag, ItemType*, int, ItemType*, ItemType*>;
111 
112 public:
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;
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 
162 protected:
164  : Element(element)
165  {
166  }
167 
168 private:
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.
183 template <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.
195  using reference = ItemType*;
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 
209  iterator begin() const
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 
231 private:
233 };
234 
235 }
236 } // end namespace vtk::detail
237 
238 #endif // vtkCollectionRange_h
239 
240 // VTK-HeaderTest-Exclude: vtkCollectionRange.h
vtkCollectionElement * Next
Definition: vtkCollection.h:49
@ reference
Definition: vtkX3D.h:470
@ value
Definition: vtkX3D.h:226
@ type
Definition: vtkX3D.h:522
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
typename Superclass::reference reference
CollectionIterator & operator=(const CollectionIterator &o) noexcept=default
typename Superclass::difference_type difference_type
typename Superclass::pointer pointer
CollectionIterator & operator++() noexcept
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:51
This file contains a variety of metaprogramming constructs for working with vtk types.