OpenVDB  10.0.1
TypeList.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 /// @file TypeList.h
5 ///
6 /// @brief A TypeList provides a compile time sequence of heterogeneous types
7 /// which can be accessed, transformed and executed over in various ways.
8 /// It incorporates a subset of functionality similar to boost::mpl::vector
9 /// however provides most of its content through using declarations rather
10 /// than additional typed classes.
11 
12 #ifndef OPENVDB_TYPELIST_HAS_BEEN_INCLUDED
13 #define OPENVDB_TYPELIST_HAS_BEEN_INCLUDED
14 
15 #include "version.h"
16 
17 #include <tuple>
18 #include <type_traits>
19 
20 namespace openvdb {
22 namespace OPENVDB_VERSION_NAME {
23 
24 /// @cond OPENVDB_DOCS_INTERNAL
25 
26 template<typename... Ts> struct TypeList; // forward declaration
27 
28 namespace typelist_internal {
29 
30 // Implementation details of @c TypeList
31 
32 /// @brief Dummy struct, used as the return type from invalid or out-of-range
33 /// @c TypeList queries.
34 struct NullType {};
35 
36 
37 /// @brief Type resolver for index queries
38 /// @details Defines a type at a given location within a @c TypeList or the
39 /// @c NullType if the index is out-of-range. The last template
40 /// parameter is used to determine if the index is in range.
41 /// @tparam ListT The @c TypeList
42 /// @tparam Idx The index of the type to get
43 template<typename ListT, size_t Idx, typename = void> struct TSGetElementImpl;
44 
45 /// @brief Partial specialization for valid (in range) index queries.
46 /// @tparam Ts Unpacked types from a @c TypeList
47 /// @tparam Idx The index of the type to get
48 template<typename... Ts, size_t Idx>
49 struct TSGetElementImpl<TypeList<Ts...>, Idx,
50  typename std::enable_if<(Idx < sizeof...(Ts) && sizeof...(Ts))>::type> {
51  using type = typename std::tuple_element<Idx, std::tuple<Ts...>>::type;
52 };
53 
54 /// @brief Partial specialization for invalid index queries (i.e. out-of-range
55 /// indices such as @c TypeList<Int32>::Get<1>). Defines the NullType.
56 /// @tparam Ts Unpacked types from a @c TypeList
57 /// @tparam Idx The index of the type to get
58 template<typename... Ts, size_t Idx>
59 struct TSGetElementImpl<TypeList<Ts...>, Idx,
60  typename std::enable_if<!(Idx < sizeof...(Ts) && sizeof...(Ts))>::type> {
61  using type = NullType;
62 };
63 
64 
65 /// @brief Search for a given type within a @c TypeList.
66 /// @details If the type is found, a @c bool constant @c Value is set to true
67 /// and an @c int64_t @c Index points to the location of the type. If
68 /// multiple versions of the types exist, the value of @c Index is
69 /// always the location of the first matching type. If the type is not
70 /// found, @c Value is set to false and @c Index is set to -1.
71 /// @note This implementation is recursively defined until the type is found
72 /// or until the end of the list is reached. The last template argument
73 /// is used as an internal counter to track the current index being
74 /// evaluated.
75 /// @tparam ListT The @c TypeList
76 /// @tparam T The type to find
77 template <typename ListT, typename T, size_t=0>
78 struct TSHasTypeImpl;
79 
80 /// @brief Partial specialization on an empty @c TypeList, instantiated when
81 /// @c TSHasTypeImpl has been invoked with an empty @c TypeList or when
82 /// a recursive search reaches the end of a @c TypeList.
83 /// @tparam T The type to find
84 /// @tparam Idx Current index
85 template <typename T, size_t Idx>
86 struct TSHasTypeImpl<TypeList<>, T, Idx> {
87  static constexpr bool Value = false;
88  static constexpr int64_t Index = -1;
89 };
90 
91 /// @brief Partial specialization on a @c TypeList which still contains types,
92 /// but the current type being evaluated @c U does not match the given
93 /// type @C T.
94 /// @tparam U The current type being evaluated within the @c TypeList
95 /// @tparam T The type to find
96 /// @tparam Ts Remaining types
97 /// @tparam Idx Current index
98 template <typename U, typename T, typename... Ts, size_t Idx>
99 struct TSHasTypeImpl<TypeList<U, Ts...>, T, Idx> :
100  TSHasTypeImpl<TypeList<Ts...>, T, Idx+1> {};
101 
102 /// @brief Partial specialization on a @c TypeList where @c T matches the
103 /// current type (i.e. the type has been found).
104 /// @tparam T The type to find
105 /// @tparam Ts Remaining types
106 /// @tparam Idx Current index
107 template <typename T, typename... Ts, size_t Idx>
108 struct TSHasTypeImpl<TypeList<T, Ts...>, T, Idx>
109 {
110  static constexpr bool Value = true;
111  static constexpr int64_t Index = static_cast<int64_t>(Idx);
112 };
113 
114 
115 /// @brief Similar to TsAppendImpl but only appends types to a list if the
116 /// type does not alreay exist in the list.
117 /// @details Defines a new @c TypeList with non-unique types appended
118 /// @tparam U Type to append
119 /// @tparam ListT The @c TypeList to append to
120 template <typename U, typename ListT,
121  bool ListContainsType = TSHasTypeImpl<ListT, U>::Value>
122 struct TSAppendUniqueImpl;
123 
124 /// @brief Partial specialization where the currently evaluating type @c U in
125 /// a @c TypeList already exists in the list. Returns the unmodified list.
126 /// @tparam U Type to append
127 /// @tparam Ts Other types within the @c TypeList
128 template <typename U, typename... Ts>
129 struct TSAppendUniqueImpl<U, TypeList<Ts...>, true> {
130 private:
131  using RemovedU = typename TypeList<Ts...>::template Remove<U>;
132 public:
133  /// @note It's simpler to remove the current type U and append the rest by
134  /// just having "using type = TypeList<Ts...>". However this ends up with
135  /// with keeping the last seen type rather than the first which this
136  /// method historically did. e.g:
137  /// TypeList<float, int, float>::Unique<> can become:
138  /// a) TypeList<float, int> currently
139  /// b) TypeList<int, float> if we used the afformentioned technique
140  /// Might be useful to have both? Complexity in (a) is currently linear so
141  /// this shouldn't be a problem, but be careful this doesn't change.
142  //using type = TypeList<Ts...>;
143  using type = typename TypeList<U>::template Append<RemovedU>;
144 };
145 
146 /// @brief Partial specialization where the currently evaluating type @c U in
147 /// a @c TypeList does not exists in the list. Returns the appended list.
148 /// @tparam U Type to append
149 /// @tparam Ts Other types within the @c TypeList
150 template <typename U, typename... Ts>
151 struct TSAppendUniqueImpl<U, TypeList<Ts...>, false> {
152  using type = TypeList<U, Ts...>;
153 };
154 
155 /// @brief Reconstruct a @c TypeList containing only unique types.
156 /// @details This implementation effectively rebuilds a @c TypeList by
157 /// starting with an empty @c TypeList and recursively defining an expanded
158 /// @c TypeList for every type (first to last), only if the type does not
159 /// already exist in the new @c TypeList. This has the effect of dropping all
160 /// but the first of duplicate types.
161 /// @warning This implementation previously used an embdedded std::conditional
162 /// which resulted in drastically slow compilation times. If you're changing
163 /// this implementation make sure to profile compile times with larger lists.
164 /// @tparam Ts Types within the @c TypeList
165 template <typename... Ts>
166 struct TSRecurseAppendUniqueImpl;
167 
168 /// @brief Terminate type recursion when the end of a @c TypeList is reached.
169 template <>
170 struct TSRecurseAppendUniqueImpl<> {
171  using type = TypeList<>;
172 };
173 
174 /// @brief Merge and unpack an initial @c TypeList from the first argument if
175 /// such a @c TypeList has been provided.
176 /// @tparam Ts Types within the first @c TypeList
177 /// @tparam OtherTs Other types
178 template <typename... Ts, typename... OtherTs>
179 struct TSRecurseAppendUniqueImpl<TypeList<Ts...>, OtherTs...> {
180  using type = typename TSRecurseAppendUniqueImpl<OtherTs..., Ts...>::type;
181 };
182 
183 /// @brief Recursively call TSRecurseAppendUniqueImpl with each type in the
184 /// provided @c TypeLists, rebuilding a new list with only the unique set
185 /// of types.
186 /// @tparam U Next type to check for uniqueness and append
187 /// @tparam Ts Remaining types within the @c TypeList
188 template <typename U, typename... Ts>
189 struct TSRecurseAppendUniqueImpl<U, Ts...>
190 {
191  using type = typename TSAppendUniqueImpl<U,
192  typename TSRecurseAppendUniqueImpl<Ts...>::type
193  >::type;
194 };
195 
196 
197 /// @brief Append any number of types to a @c TypeList
198 /// @details Defines a new @c TypeList with the provided types appended
199 /// @tparam ListT The @c TypeList to append to
200 /// @tparam Ts Types to append
201 template<typename ListT, typename... Ts> struct TSAppendImpl;
202 
203 /// @brief Partial specialization for a @c TypeList with a list of zero or more
204 /// types to append
205 /// @tparam Ts Current types within the @c TypeList
206 /// @tparam OtherTs Other types to append
207 template<typename... Ts, typename... OtherTs>
208 struct TSAppendImpl<TypeList<Ts...>, OtherTs...> {
209  using type = TypeList<Ts..., OtherTs...>;
210 };
211 
212 /// @brief Partial specialization for a @c TypeList with another @c TypeList.
213 /// Appends the other TypeList's members.
214 /// @tparam Ts Types within the first @c TypeList
215 /// @tparam OtherTs Types within the second @c TypeList
216 template<typename... Ts, typename... OtherTs>
217 struct TSAppendImpl<TypeList<Ts...>, TypeList<OtherTs...>> {
218  using type = TypeList<Ts..., OtherTs...>;
219 };
220 
221 
222 /// @brief Remove all occurrences of type T from a @c TypeList
223 /// @details Defines a new @c TypeList with the provided types removed
224 /// @tparam ListT The @c TypeList
225 /// @tparam T Type to remove
226 template<typename ListT, typename T> struct TSEraseImpl;
227 
228 /// @brief Partial specialization for an empty @c TypeList
229 /// @tparam T Type to remove, has no effect
230 template<typename T>
231 struct TSEraseImpl<TypeList<>, T> { using type = TypeList<>; };
232 
233 /// @brief Partial specialization where the currently evaluating type in a
234 /// @c TypeList matches the type to remove. Recursively defines this
235 /// implementation with the remaining types.
236 /// @tparam Ts Unpacked types within the @c TypeList
237 /// @tparam T Type to remove
238 template<typename... Ts, typename T>
239 struct TSEraseImpl<TypeList<T, Ts...>, T> {
240  using type = typename TSEraseImpl<TypeList<Ts...>, T>::type;
241 };
242 
243 /// @brief Partial specialization where the currently evaluating type @c T2 in
244 /// a @c TypeList does not match the type to remove @c T. Recursively
245 /// defines this implementation with the remaining types.
246 /// @tparam T2 Current type within the @c TypeList, which does not match @c T
247 /// @tparam Ts Other types within the @c TypeList
248 /// @tparam T Type to remove
249 template<typename T2, typename... Ts, typename T>
250 struct TSEraseImpl<TypeList<T2, Ts...>, T> {
251  using type = typename TSAppendImpl<TypeList<T2>,
252  typename TSEraseImpl<TypeList<Ts...>, T>::type>::type;
253 };
254 
255 /// @brief Front end implementation to call TSEraseImpl which removes all
256 /// occurrences of a type from a @c TypeList. This struct handles the
257 /// case where the type to remove is another @c TypeList, in which case
258 /// all types in the second @c TypeList are removed from the first.
259 /// @tparam ListT The @c TypeList
260 /// @tparam Ts Types in the @c TypeList
261 template<typename ListT, typename... Ts> struct TSRemoveImpl;
262 
263 /// @brief Partial specialization when there are no types in the @c TypeList.
264 /// @tparam ListT The @c TypeList
265 template<typename ListT>
266 struct TSRemoveImpl<ListT> { using type = ListT; };
267 
268 /// @brief Partial specialization when the type to remove @c T is not another
269 /// @c TypeList. @c T is removed from the @c TypeList.
270 /// @tparam ListT The @c TypeList
271 /// @tparam T Type to remove
272 /// @tparam Ts Types in the @c TypeList
273 template<typename ListT, typename T, typename... Ts>
274 struct TSRemoveImpl<ListT, T, Ts...> {
275  using type = typename TSRemoveImpl<typename TSEraseImpl<ListT, T>::type, Ts...>::type;
276 };
277 
278 /// @brief Partial specialization when the type to remove is another
279 /// @c TypeList. All types within the other type list are removed from
280 /// the first list.
281 /// @tparam ListT The @c TypeList
282 /// @tparam Ts Types from the second @c TypeList to remove from the first
283 template<typename ListT, typename... Ts>
284 struct TSRemoveImpl<ListT, TypeList<Ts...>> {
285  using type = typename TSRemoveImpl<ListT, Ts...>::type;
286 };
287 
288 /// @brief Remove the first element of a type list. If the list is empty,
289 /// nothing is done. This base configuration handles the empty list.
290 /// @note Much cheaper to instantiate than TSRemoveIndicesImpl
291 /// @tparam T The @c TypeList
292 template<typename T>
293 struct TSRemoveFirstImpl {
294  using type = TypeList<>;
295 };
296 
297 /// @brief Partial specialization for removing the first type of a @c TypeList
298 /// when the list is not empty i.e. does that actual work.
299 /// @tparam T The first type in the @c TypeList.
300 /// @tparam Ts Remaining types in the @c TypeList
301 template<typename T, typename... Ts>
302 struct TSRemoveFirstImpl<TypeList<T, Ts...>> {
303  using type = TypeList<Ts...>;
304 };
305 
306 
307 /// @brief Remove the last element of a type list. If the list is empty,
308 /// nothing is done. This base configuration handles the empty list.
309 /// @note Cheaper to instantiate than TSRemoveIndicesImpl
310 /// @tparam T The @c TypeList
311 template<typename T>
312 struct TSRemoveLastImpl { using type = TypeList<>; };
313 
314 /// @brief Partial specialization for removing the last type of a @c TypeList.
315 /// This instance is instantiated when the @c TypeList contains a
316 /// single type, or the primary struct which recursively removes types
317 /// (see below) hits the last type. Evaluates the last type to the empty
318 /// list (see above).
319 /// @tparam T The last type in the @c TypeList
320 template<typename T>
321 struct TSRemoveLastImpl<TypeList<T>> : TSRemoveLastImpl<T> {};
322 
323 /// @brief Partial specialization for removing the last type of a @c TypeList
324 /// with a type list size of two or more. Recursively defines this
325 /// implementation with the remaining types, effectively rebuilding the
326 /// @c TypeList until the last type is hit, which is dropped.
327 /// @tparam T The current type in the @c TypeList
328 /// @tparam Ts Remaining types in the @c TypeList
329 template<typename T, typename... Ts>
330 struct TSRemoveLastImpl<TypeList<T, Ts...>>
331 {
332  using type =
333  typename TypeList<T>::template
334  Append<typename TSRemoveLastImpl<TypeList<Ts...>>::type>;
335 };
336 
337 
338 /// @brief Remove a number of types from a @c TypeList based on a @c First and
339 /// @c Last index.
340 /// @details Both indices are inclusive, such that when <tt>First == Last</tt>
341 /// a single type is removed (assuming the index exists). If
342 /// <tt>Last < First</tt>, nothing is done. Any indices which do not
343 /// exist are ignored. If @c Last is greater than the number of types
344 /// in the @c TypeList, all types from @c First to the end of the list
345 /// are dropped.
346 /// @tparam ListT The @c TypeList
347 /// @tparam First The first index
348 /// @tparam Last The last index
349 /// @tparam Idx Internal counter for the current index
350 template<typename ListT, size_t First, size_t Last, size_t Idx=0>
351 struct TSRemoveIndicesImpl;
352 
353 /// @brief Partial specialization for an empty @c TypeList
354 /// @tparam First The first index
355 /// @tparam Last The last index
356 /// @tparam Idx Internal counter for the current index
357 template<size_t First, size_t Last, size_t Idx>
358 struct TSRemoveIndicesImpl<TypeList<>, First, Last, Idx> {
359  using type = TypeList<>;
360 };
361 
362 /// @brief Partial specialization for a @c TypeList containing a single element.
363 /// @tparam T The last or only type in a @c TypeList
364 /// @tparam First The first index
365 /// @tparam Last The last index
366 /// @tparam Idx Internal counter for the current index
367 template<typename T, size_t First, size_t Last, size_t Idx>
368 struct TSRemoveIndicesImpl<TypeList<T>, First, Last, Idx>
369 {
370 private:
371  static constexpr bool Remove = Idx >= First && Idx <= Last;
372 public:
373  using type = typename std::conditional<Remove, TypeList<>, TypeList<T>>::type;
374 };
375 
376 /// @brief Partial specialization for a @c TypeList containing two or more types.
377 /// @details This implementation effectively rebuilds a @c TypeList by starting
378 /// with an empty @c TypeList and recursively defining an expanded
379 /// @c TypeList for every type (first to last), only if the type's
380 /// index does not fall within the range of indices defines by
381 /// @c First and @c Last. Recursively defines this implementation with
382 /// all but the last type.
383 /// @tparam T The currently evaluating type within a @c TypeList
384 /// @tparam Ts Remaining types in the @c TypeList
385 /// @tparam First The first index
386 /// @tparam Last The last index
387 /// @tparam Idx Internal counter for the current index
388 template<typename T, typename... Ts, size_t First, size_t Last, size_t Idx>
389 struct TSRemoveIndicesImpl<TypeList<T, Ts...>, First, Last, Idx>
390 {
391 private:
392  using ThisList = typename TSRemoveIndicesImpl<TypeList<T>, First, Last, Idx>::type;
393  using NextList = typename TSRemoveIndicesImpl<TypeList<Ts...>, First, Last, Idx+1>::type;
394 public:
395  using type = typename ThisList::template Append<NextList>;
396 };
397 
398 /// @brief Transform a @c TypeList, converting each type into a new type based
399 /// on a transformation struct @c OpT.
400 /// @details This implementation iterates through each type in a @c TypeList
401 /// and builds a new @c TypeList where each element is resolved through
402 /// a user provided converter which provides a @c Type definition.
403 /// @tparam OpT User struct to convert each type
404 /// @tparam Ts Remaining types in the @c TypeList
405 template<template <typename> class OpT, typename... Ts> struct TSTranformImpl;
406 
407 /// @brief Partial specialization for an empty @c TypeList
408 /// @tparam OpT User struct to convert each type
409 template<template <typename> class OpT>
410 struct TSTranformImpl<OpT> {
411  using type = TypeList<>;
412 };
413 
414 /// @brief Implementation of TSTranformImpl. See fwd declaration for details.
415 /// @tparam OpT User struct to convert each type
416 /// @tparam Ts Remaining types in the @c TypeList
417 /// @tparam T Current type being converted
418 template<template <typename> class OpT, typename T, typename... Ts>
419 struct TSTranformImpl<OpT, T, Ts...> {
420 private:
421  using NextList = typename TSTranformImpl<OpT, Ts...>::type;
422 public:
423  // Invoke Append for each type to match the behaviour should OpT<T> be a
424  // TypeList<>
425  using type = typename TSTranformImpl<OpT>::type::template
426  Append<OpT<T>>::template
427  Append<NextList>;
428 };
429 
430 
431 template<typename OpT> inline void TSForEachImpl(OpT) {}
432 template<typename OpT, typename T, typename... Ts>
433 inline void TSForEachImpl(OpT op) { op(T()); TSForEachImpl<OpT, Ts...>(op); }
434 
435 template<template <typename> class OpT> inline void TSForEachImpl() {}
436 template<template <typename> class OpT, typename T, typename... Ts>
437 inline void TSForEachImpl() { OpT<T>()(); TSForEachImpl<OpT, Ts...>(); }
438 
439 
440 /// @brief Partial apply specialization for an empty @c TypeList
441 /// @tparam OpT User functor to apply to the first valid type
442 /// @tparam BaseT Type of the provided obj
443 /// @tparam T Current type
444 /// @tparam Ts Remaining types
445 template<typename OpT, typename BaseT, typename T, typename ...Ts>
446 struct TSApplyImpl { static bool apply(BaseT&, OpT&) { return false; } };
447 
448 /// @brief Apply a unary functor to a provided object only if the object
449 /// satisfies the cast requirement of isType<T> for a type in a TypeList.
450 /// @note Iteration terminates immediately on the first valid type and true
451 /// is returned.
452 /// @tparam OpT User functor to apply to the first valid type
453 /// @tparam BaseT Type of the provided obj
454 /// @tparam T Current type
455 /// @tparam Ts Remaining types
456 template<typename OpT, typename BaseT, typename T, typename ...Ts>
457 struct TSApplyImpl<OpT, BaseT, TypeList<T, Ts...>>
458 {
459  using CastT =
460  typename std::conditional<std::is_const<BaseT>::value, const T, T>::type;
461 
462  static bool apply(BaseT& obj, OpT& op)
463  {
464  if (obj.template isType<T>()) {
465  op(static_cast<CastT&>(obj));
466  return true;
467  }
468  return TSApplyImpl<OpT, BaseT, TypeList<Ts...>>::apply(obj, op);
469  }
470 };
471 
472 } // namespace internal
473 
474 /// @endcond
475 
476 
477 /// @brief A list of types (not necessarily unique)
478 /// @details Example:
479 /// @code
480 /// using MyTypes = openvdb::TypeList<int, float, int, double, float>;
481 /// @endcode
482 template<typename... Ts>
483 struct TypeList
484 {
485  /// The type of this list
486  using Self = TypeList;
487 
488  /// @brief The number of types in the type list
489  static constexpr size_t Size = sizeof...(Ts);
490 
491  /// @brief Access a particular element of this type list. If the index
492  /// is out of range, typelist_internal::NullType is returned.
493  template<size_t N>
494  using Get = typename typelist_internal::TSGetElementImpl<Self, N>::type;
495  using Front = Get<0>;
496  using Back = Get<Size-1>;
497 
498  /// @brief True if this list contains the given type, false otherwise
499  /// @details Example:
500  /// @code
501  /// {
502  /// using IntTypes = openvdb::TypeList<Int16, Int32, Int64>;
503  /// using RealTypes = openvdb::TypeList<float, double>;
504  /// }
505  /// {
506  /// openvdb::TypeList<IntTypes>::Contains<Int32>; // true
507  /// openvdb::TypeList<RealTypes>::Contains<Int32>; // false
508  /// }
509  /// @endcode
510  template<typename T>
511  static constexpr bool Contains = typelist_internal::TSHasTypeImpl<Self, T>::Value;
512 
513  /// @brief Returns the index of the first found element of the given type, -1 if
514  /// no matching element exists.
515  /// @details Example:
516  /// @code
517  /// {
518  /// using IntTypes = openvdb::TypeList<Int16, Int32, Int64>;
519  /// using RealTypes = openvdb::TypeList<float, double>;
520  /// }
521  /// {
522  /// const int64_t L1 = openvdb::TypeList<IntTypes>::Index<Int32>; // 1
523  /// const int64_t L2 = openvdb::TypeList<RealTypes>::Index<Int32>; // -1
524  /// }
525  /// @endcode
526  template<typename T>
528 
529  /// @brief Remove any duplicate types from this TypeList by rotating the
530  /// next valid type left (maintains the order of other types). Optionally
531  /// combine the result with another TypeList.
532  /// @details Example:
533  /// @code
534  /// {
535  /// using Types = openvdb::TypeList<Int16, Int32, Int16, float, float, Int64>;
536  /// }
537  /// {
538  /// using UniqueTypes = Types::Unique<>; // <Int16, Int32, float, Int64>
539  /// }
540  /// @endcode
541  template<typename ListT = TypeList<>>
542  using Unique = typename typelist_internal::TSRecurseAppendUniqueImpl<ListT, Ts...>::type;
543 
544  /// @brief Append types, or the members of another TypeList, to this list.
545  /// @warning Appending nested TypeList<> objects causes them to expand to
546  /// their contained list of types.
547  /// @details Example:
548  /// @code
549  /// {
550  /// using IntTypes = openvdb::TypeList<Int16, Int32, Int64>;
551  /// using RealTypes = openvdb::TypeList<float, double>;
552  /// using NumericTypes = IntTypes::Append<RealTypes>;
553  /// }
554  /// {
555  /// using IntTypes = openvdb::TypeList<Int16>::Append<Int32, Int64>;
556  /// using NumericTypes = IntTypes::Append<float>::Append<double>;
557  /// }
558  /// @endcode
559  template<typename... TypesToAppend>
560  using Append = typename typelist_internal::TSAppendImpl<Self, TypesToAppend...>::type;
561 
562  /// @brief Remove all occurrences of one or more types, or the members of
563  /// another TypeList, from this list.
564  /// @details Example:
565  /// @code
566  /// {
567  /// using NumericTypes = openvdb::TypeList<float, double, Int16, Int32, Int64>;
568  /// using LongTypes = openvdb::TypeList<Int64, double>;
569  /// using ShortTypes = NumericTypes::Remove<LongTypes>; // float, Int16, Int32
570  /// }
571  /// @endcode
572  template<typename... TypesToRemove>
573  using Remove = typename typelist_internal::TSRemoveImpl<Self, TypesToRemove...>::type;
574 
575  /// @brief Remove the first element of this type list. Has no effect if the
576  /// type list is already empty.
577  /// @details Example:
578  /// @code
579  /// {
580  /// using IntTypes = openvdb::TypeList<Int16, Int32, Int64>;
581  /// using EmptyTypes = openvdb::TypeList<>;
582  /// }
583  /// {
584  /// IntTypes::PopFront; // openvdb::TypeList<Int32, Int64>;
585  /// EmptyTypes::PopFront; // openvdb::TypeList<>;
586  /// }
587  /// @endcode
588  using PopFront = typename typelist_internal::TSRemoveFirstImpl<Self>::type;
589 
590  /// @brief Remove the last element of this type list. Has no effect if the
591  /// type list is already empty.
592  /// @details Example:
593  /// @code
594  /// {
595  /// using IntTypes = openvdb::TypeList<Int16, Int32, Int64>;
596  /// using EmptyTypes = openvdb::TypeList<>;
597  /// }
598  /// {
599  /// IntTypes::PopBack; // openvdb::TypeList<Int16, Int32>;
600  /// EmptyTypes::PopBack; // openvdb::TypeList<>;
601  /// }
602  /// @endcode
603  using PopBack = typename typelist_internal::TSRemoveLastImpl<Self>::type;
604 
605  /// @brief Return a new list with types removed by their location within the list.
606  /// If First is equal to Last, a single element is removed (if it exists).
607  /// If First is greater than Last, the list remains unmodified.
608  /// @details Example:
609  /// @code
610  /// {
611  /// using NumericTypes = openvdb::TypeList<float, double, Int16, Int32, Int64>;
612  /// }
613  /// {
614  /// using IntTypes = NumericTypes::RemoveByIndex<0,1>; // openvdb::TypeList<Int16, Int32, Int64>;
615  /// using RealTypes = NumericTypes::RemoveByIndex<2,4>; // openvdb::TypeList<float, double>;
616  /// using RemoveFloat = NumericTypes::RemoveByIndex<0,0>; // openvdb::TypeList<double, Int16, Int32, Int64>;
617  /// }
618  /// @endcode
619  template <size_t First, size_t Last>
620  using RemoveByIndex = typename typelist_internal::TSRemoveIndicesImpl<Self, First, Last>::type;
621 
622  /// @brief Transform each type of this TypeList, rebuiling a new list of
623  /// converted types. This method instantiates a user provided Opt<T> to
624  /// replace each type in the current list.
625  /// @warning Transforming types to new TypeList<> objects causes them to expand to
626  /// their contained list of types.
627  /// @details Example:
628  /// @code
629  /// {
630  /// // Templated type decl, where the type T will be subsituted for each type
631  /// // in the TypeList being transformed.
632  /// template <typename T>
633  /// using ConvertedType = typename openvdb::PromoteType<T>::Next;
634  ///
635  /// // Results in: openvdb::TypeList<Int64, double>;
636  /// using PromotedType = openvdb::TypeList<Int32, float>::Transform<ConvertedType>;
637  /// }
638  /// @endcode
639  template<template <typename> class OpT>
640  using Transform = typename typelist_internal::TSTranformImpl<OpT, Ts...>::type;
641 
642  /// @brief Invoke a templated class operator on each type in this list. Use
643  /// this method if you only need access to the type for static methods.
644  /// @details Example:
645  /// @code
646  /// #include <typeinfo>
647  ///
648  /// template <typename T>
649  /// struct PintTypes() {
650  /// inline void operator()() { std::cout << typeid(T).name() << std::endl; }
651  /// };
652  ///
653  /// using MyTypes = openvdb::TypeList<int, float, double>;
654  /// MyTypes::foreach<PintTypes>(); // "i, f, d" (exact output is compiler-dependent)
655  /// @endcode
656  ///
657  /// @note OpT must be a templated class. It is created and invoked for each
658  /// type in this list.
659  template<template <typename> class OpT>
660  static void foreach() { typelist_internal::TSForEachImpl<OpT, Ts...>(); }
661 
662  /// @brief Invoke a templated, unary functor on a value of each type in this list.
663  /// @details Example:
664  /// @code
665  /// #include <typeinfo>
666  ///
667  /// template<typename ListT>
668  /// void printTypeList()
669  /// {
670  /// std::string sep;
671  /// auto op = [&](auto x) { // C++14
672  /// std::cout << sep << typeid(decltype(x)).name(); sep = ", "; };
673  /// ListT::foreach(op);
674  /// }
675  ///
676  /// using MyTypes = openvdb::TypeList<int, float, double>;
677  /// printTypeList<MyTypes>(); // "i, f, d" (exact output is compiler-dependent)
678  /// @endcode
679  ///
680  /// @note The functor object is passed by value. Wrap it with @c std::ref
681  /// to use the same object for each type.
682  template<typename OpT>
683  static void foreach(OpT op) { typelist_internal::TSForEachImpl<OpT, Ts...>(op); }
684 
685  /// @brief Invoke a templated, unary functor on a provide @c obj of type
686  /// @c BaseT only if said object is an applicable (derived) type
687  /// also contained in the current @c TypeList.
688  /// @details This method loops over every type in the type list and calls
689  /// an interface method on @c obj to check to see if the @c obj is
690  /// interpretable as the given type. If it is, the method static casts
691  /// @c obj to the type, invokes the provided functor with the casted type
692  /// and returns, stopping further list iteration. @c obj is expected to
693  /// supply an interface to validate the type which satisfies the
694  /// prototype:
695  /// @code
696  /// template <typename T> bool isType()
697  /// @endcode
698  ///
699  /// A full example (using dynamic_cast - see Grid/Tree implementations
700  /// for string based comparisons:
701  /// @code
702  /// struct Base {
703  /// virtual ~Base() = default;
704  /// template<typename T> bool isType() { return dynamic_cast<const T*>(this); }
705  /// };
706  /// struct MyType1 : public Base { void print() { std::cerr << "MyType1" << std::endl; } };
707  /// struct MyType2 : public Base { void print() { std::cerr << "MyType2" << std::endl; } };
708  ///
709  /// using MyTypeList = TypeList<MyType1, MyType2>;
710  /// Base* getObj() { return new MyType2(); }
711  ///
712  /// std::unique_ptr<Base> obj = getObj();
713  /// // Returns 'true', prints 'MyType2'
714  /// const bool success =
715  /// MyTypeList::apply([](const auto& type) { type.print(); }, *obj);
716  /// @endcode
717  ///
718  /// @note The functor object is passed by value. Wrap it with @c std::ref
719  /// pass by reference.
720  template<typename OpT, typename BaseT>
721  static bool apply(OpT op, BaseT& obj) {
722  return typelist_internal::TSApplyImpl<OpT, BaseT, Self>::apply(obj, op);
723  }
724 };
725 
726 
727 } // namespace OPENVDB_VERSION_NAME
728 } // namespace openvdb
729 
730 
731 #endif // OPENVDB_TYPELIST_HAS_BEEN_INCLUDED
typename typelist_internal::TSGetElementImpl< Self, N >::type Get
Access a particular element of this type list. If the index is out of range, typelist_internal::NullT...
Definition: TypeList.h:494
Index32 Index
Definition: Types.h:54
typename typelist_internal::TSRemoveFirstImpl< Self >::type PopFront
Remove the first element of this type list. Has no effect if the type list is already empty...
Definition: TypeList.h:588
typename typelist_internal::TSRecurseAppendUniqueImpl< ListT, Ts... >::type Unique
Remove any duplicate types from this TypeList by rotating the next valid type left (maintains the ord...
Definition: TypeList.h:542
Definition: Coord.h:587
A list of types (not necessarily unique)
Definition: TypeList.h:483
typename typelist_internal::TSRemoveImpl< Self, TypesToRemove... >::type Remove
Remove all occurrences of one or more types, or the members of another TypeList, from this list...
Definition: TypeList.h:573
Get< Size-1 > Back
Definition: TypeList.h:496
typename typelist_internal::TSAppendImpl< Self, TypesToAppend... >::type Append
Append types, or the members of another TypeList, to this list.
Definition: TypeList.h:560
Definition: Exceptions.h:13
typename typelist_internal::TSRemoveIndicesImpl< Self, First, Last >::type RemoveByIndex
Return a new list with types removed by their location within the list. If First is equal to Last...
Definition: TypeList.h:620
ValueT value
Definition: GridBuilder.h:1290
typename typelist_internal::TSRemoveLastImpl< Self >::type PopBack
Remove the last element of this type list. Has no effect if the type list is already empty...
Definition: TypeList.h:603
static bool apply(OpT op, BaseT &obj)
Invoke a templated, unary functor on a provide obj of type BaseT only if said object is an applicable...
Definition: TypeList.h:721
Get< 0 > Front
Definition: TypeList.h:495
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:212
typename typelist_internal::TSTranformImpl< OpT, Ts... >::type Transform
Transform each type of this TypeList, rebuiling a new list of converted types. This method instantiat...
Definition: TypeList.h:640