OpenVDB 10.0.1
Loading...
Searching...
No Matches
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
20namespace openvdb {
22namespace OPENVDB_VERSION_NAME {
23
24/// @cond OPENVDB_DOCS_INTERNAL
25
26template<typename... Ts> struct TypeList; // forward declaration
27
28namespace 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.
34struct 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
43template<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
48template<typename... Ts, size_t Idx>
49struct 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
58template<typename... Ts, size_t Idx>
59struct 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
77template <typename ListT, typename T, size_t=0>
78struct 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
85template <typename T, size_t Idx>
86struct 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
98template <typename U, typename T, typename... Ts, size_t Idx>
99struct 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
107template <typename T, typename... Ts, size_t Idx>
108struct 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
120template <typename U, typename ListT,
121 bool ListContainsType = TSHasTypeImpl<ListT, U>::Value>
122struct 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
128template <typename U, typename... Ts>
129struct TSAppendUniqueImpl<U, TypeList<Ts...>, true> {
130private:
131 using RemovedU = typename TypeList<Ts...>::template Remove<U>;
132public:
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
150template <typename U, typename... Ts>
151struct 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
165template <typename... Ts>
166struct TSRecurseAppendUniqueImpl;
167
168/// @brief Terminate type recursion when the end of a @c TypeList is reached.
169template <>
170struct 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
178template <typename... Ts, typename... OtherTs>
179struct 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
188template <typename U, typename... Ts>
189struct 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
201template<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
207template<typename... Ts, typename... OtherTs>
208struct 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
216template<typename... Ts, typename... OtherTs>
217struct 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
226template<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
230template<typename T>
231struct 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
238template<typename... Ts, typename T>
239struct 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
249template<typename T2, typename... Ts, typename T>
250struct 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
261template<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
265template<typename ListT>
266struct 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
273template<typename ListT, typename T, typename... Ts>
274struct 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
283template<typename ListT, typename... Ts>
284struct 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
292template<typename T>
293struct 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
301template<typename T, typename... Ts>
302struct 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
311template<typename T>
312struct 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
320template<typename T>
321struct 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
329template<typename T, typename... Ts>
330struct 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
350template<typename ListT, size_t First, size_t Last, size_t Idx=0>
351struct 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
357template<size_t First, size_t Last, size_t Idx>
358struct 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
367template<typename T, size_t First, size_t Last, size_t Idx>
368struct TSRemoveIndicesImpl<TypeList<T>, First, Last, Idx>
369{
370private:
371 static constexpr bool Remove = Idx >= First && Idx <= Last;
372public:
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
388template<typename T, typename... Ts, size_t First, size_t Last, size_t Idx>
389struct TSRemoveIndicesImpl<TypeList<T, Ts...>, First, Last, Idx>
390{
391private:
392 using ThisList = typename TSRemoveIndicesImpl<TypeList<T>, First, Last, Idx>::type;
393 using NextList = typename TSRemoveIndicesImpl<TypeList<Ts...>, First, Last, Idx+1>::type;
394public:
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
405template<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
409template<template <typename> class OpT>
410struct 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
418template<template <typename> class OpT, typename T, typename... Ts>
419struct TSTranformImpl<OpT, T, Ts...> {
420private:
421 using NextList = typename TSTranformImpl<OpT, Ts...>::type;
422public:
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
431template<typename OpT> inline void TSForEachImpl(OpT) {}
432template<typename OpT, typename T, typename... Ts>
433inline void TSForEachImpl(OpT op) { op(T()); TSForEachImpl<OpT, Ts...>(op); }
434
435template<template <typename> class OpT> inline void TSForEachImpl() {}
436template<template <typename> class OpT, typename T, typename... Ts>
437inline 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
445template<typename OpT, typename BaseT, typename T, typename ...Ts>
446struct 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
456template<typename OpT, typename BaseT, typename T, typename ...Ts>
457struct 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
482template<typename... Ts>
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>
527 static constexpr int64_t Index = typelist_internal::TSHasTypeImpl<Self, T>::Index;
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
Index32 Index
Definition Types.h:54
Definition Exceptions.h:13
Definition Coord.h:587
A list of types (not necessarily unique)
Definition TypeList.h:484
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< 0 > Front
Definition TypeList.h:495
Get< Size-1 > Back
Definition TypeList.h:496
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
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
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
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::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
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
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
typename typelist_internal::TSAppendImpl< Self, TypesToAppend... >::type Append
Append types, or the members of another TypeList, to this list.
Definition TypeList.h:560
#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