GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/TypeList.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 10 10 100.0%
Functions: 171 225 76.0%
Branches: 46 87 52.9%

Line Branch Exec Source
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 {
21 OPENVDB_USE_VERSION_NAMESPACE
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
3/5
✓ Branch 0 taken 90342 times.
✓ Branch 1 taken 50190 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
361464 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
3/6
✓ Branch 1 taken 323 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 323 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 323 times.
✗ Branch 8 not taken.
22023 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 88578 static bool apply(BaseT& obj, OpT& op)
463 {
464
14/25
✓ Branch 1 taken 6624 times.
✓ Branch 2 taken 37666 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 25 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
88584 if (obj.template isType<T>()) {
465
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
3408 op(static_cast<CastT&>(obj));
466 13257 return true;
467 }
468 75270 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>
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 970 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
8/15
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
5047 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
16/32
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4915 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
6654 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
732