VTK  9.1.20211115
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 
28 namespace vtk
29 {
30 namespace detail
31 {
32 
33 template <typename CollectionType>
34 struct CollectionRange;
35 template <typename CollectionType>
36 struct CollectionIterator;
37 
38 //------------------------------------------------------------------------------
39 // Detect vtkCollection types
40 template <typename T>
41 struct IsCollection : std::is_base_of<vtkCollection, T>
42 {
43 };
44 
45 template <typename CollectionType, typename T = CollectionType>
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.
51 template <typename CollectionType>
53 {
54  static_assert(IsCollection<CollectionType>::value, "Invalid vtkCollection subclass.");
55 
56 private:
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 
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>
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 
110 private:
111  using ItemType = typename GetCollectionItemType<CollectionType>::Type;
112  using Superclass = std::iterator<std::forward_iterator_tag, ItemType*, int, ItemType*, ItemType*>;
113 
114 public:
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;
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 
164 protected:
166  : Element(element)
167  {
168  }
169 
170 private:
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.
185 template <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.
197  using reference = ItemType*;
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 
211  iterator begin() const
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 
233 private:
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
@ 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:48
This file contains a variety of metaprogramming constructs for working with vtk types.