Skip to content

Commit 9bf2128

Browse files
authored
Merge pull request #1367 from Idclip/feature/typelists
More additions to TypeLists
2 parents 712e52b + 2d271ea commit 9bf2128

File tree

7 files changed

+313
-79
lines changed

7 files changed

+313
-79
lines changed

openvdb/openvdb/Grid.h

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,61 +1767,36 @@ createLevelSet(Real voxelSize, Real halfWidth)
17671767

17681768
////////////////////////////////////////
17691769

1770-
/// @cond OPENVDB_DOCS_INTERNAL
1771-
1772-
namespace internal {
1773-
1774-
/// @private
1775-
template<typename OpT, typename GridBaseT, typename T, typename ...Ts>
1776-
struct GridApplyImpl { static bool apply(GridBaseT&, OpT&) { return false; } };
1777-
1778-
// Partial specialization for (nonempty) TypeLists
1779-
/// @private
1780-
template<typename OpT, typename GridBaseT, typename GridT, typename ...GridTs>
1781-
struct GridApplyImpl<OpT, GridBaseT, TypeList<GridT, GridTs...>>
1782-
{
1783-
static bool apply(GridBaseT& grid, OpT& op)
1784-
{
1785-
if (grid.template isType<GridT>()) {
1786-
op(static_cast<typename CopyConstness<GridBaseT, GridT>::Type&>(grid));
1787-
return true;
1788-
}
1789-
return GridApplyImpl<OpT, GridBaseT, TypeList<GridTs...>>::apply(grid, op);
1790-
}
1791-
};
1792-
1793-
} // namespace internal
1794-
1795-
/// @endcond
17961770

17971771
template<typename GridTypeListT, typename OpT>
17981772
inline bool
17991773
GridBase::apply(OpT& op) const
18001774
{
1801-
return internal::GridApplyImpl<OpT, const GridBase, GridTypeListT>::apply(*this, op);
1775+
return GridTypeListT::template apply<OpT&, const GridBase>(std::ref(op), *this);
18021776
}
18031777

18041778
template<typename GridTypeListT, typename OpT>
18051779
inline bool
18061780
GridBase::apply(OpT& op)
18071781
{
1808-
return internal::GridApplyImpl<OpT, GridBase, GridTypeListT>::apply(*this, op);
1782+
return GridTypeListT::template apply<OpT&, GridBase>(std::ref(op), *this);
18091783
}
18101784

18111785
template<typename GridTypeListT, typename OpT>
18121786
inline bool
18131787
GridBase::apply(const OpT& op) const
18141788
{
1815-
return internal::GridApplyImpl<const OpT, const GridBase, GridTypeListT>::apply(*this, op);
1789+
return GridTypeListT::template apply<const OpT&, const GridBase>(std::ref(op), *this);
18161790
}
18171791

18181792
template<typename GridTypeListT, typename OpT>
18191793
inline bool
18201794
GridBase::apply(const OpT& op)
18211795
{
1822-
return internal::GridApplyImpl<const OpT, GridBase, GridTypeListT>::apply(*this, op);
1796+
return GridTypeListT::template apply<const OpT&, GridBase>(std::ref(op), *this);
18231797
}
18241798

1799+
18251800
} // namespace OPENVDB_VERSION_NAME
18261801
} // namespace openvdb
18271802

openvdb/openvdb/TypeList.h

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,38 @@ struct TSRemoveIndicesImpl<TypeList<T, Ts...>, First, Last, Idx>
395395
using type = typename ThisList::template Append<NextList>;
396396
};
397397

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+
398430

399431
template<typename OpT> inline void TSForEachImpl(OpT) {}
400432
template<typename OpT, typename T, typename... Ts>
@@ -404,6 +436,39 @@ template<template <typename> class OpT> inline void TSForEachImpl() {}
404436
template<template <typename> class OpT, typename T, typename... Ts>
405437
inline void TSForEachImpl() { OpT<T>()(); TSForEachImpl<OpT, Ts...>(); }
406438

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+
407472
} // namespace internal
408473

409474
/// @endcond
@@ -477,6 +542,8 @@ struct TypeList
477542
using Unique = typename typelist_internal::TSRecurseAppendUniqueImpl<ListT, Ts...>::type;
478543

479544
/// @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.
480547
/// @details Example:
481548
/// @code
482549
/// {
@@ -552,8 +619,29 @@ struct TypeList
552619
template <size_t First, size_t Last>
553620
using RemoveByIndex = typename typelist_internal::TSRemoveIndicesImpl<Self, First, Last>::type;
554621

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+
555642
/// @brief Invoke a templated class operator on each type in this list. Use
556643
/// this method if you only need access to the type for static methods.
644+
/// @details Example:
557645
/// @code
558646
/// #include <typeinfo>
559647
///
@@ -593,6 +681,46 @@ struct TypeList
593681
/// to use the same object for each type.
594682
template<typename OpT>
595683
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+
}
596724
};
597725

598726

openvdb/openvdb/openvdb.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ using IntegerGridTypes = TypeList<Int32Grid, Int64Grid>;
9696
/// this list does not include Bool or Mask Grids.
9797
using NumericGridTypes = RealGridTypes::Append<IntegerGridTypes>;
9898
/// The Vec3 Grid types which OpenVDB will register by default.
99-
using Vec3GridTypes = TypeList<Vec3IGrid, Vec3SGrid, Vec3DGrid>;
99+
using Vec3GridTypes = TypeList<Vec3IGrid, Vec3SGrid, Vec3DGrid>;
100100

101101
/// The Grid types which OpenVDB will register by default.
102102
using GridTypes =
@@ -111,6 +111,19 @@ using GridTypes =
111111
/// @}
112112

113113

114+
namespace internal {
115+
template <typename T> using ToTreeType = typename T::TreeType;
116+
}
117+
/// @name Lists of native Tree Types
118+
/// @{
119+
using RealTreeTypes = RealGridTypes::Transform<internal::ToTreeType>;
120+
using IntegerTreeTypes = IntegerGridTypes::Transform<internal::ToTreeType>;
121+
using NumericTreeTypes = NumericGridTypes::Transform<internal::ToTreeType>;
122+
using Vec3TreeTypes = Vec3GridTypes::Transform<internal::ToTreeType>;
123+
using TreeTypes = GridTypes::Transform<internal::ToTreeType>;
124+
/// @}
125+
126+
114127
/// @name Lists of native TypedAttributeArray Types (for PointDataGrids)
115128
/// @{
116129
/// The floating point attribute array types which OpenVDB will register by default.

openvdb/openvdb/tree/Tree.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ class OPENVDB_API TreeBase
5050
/// Return the name of the type of a voxel's value (e.g., "float" or "vec3d").
5151
virtual Name valueType() const = 0;
5252

53+
/// Return @c true if this tree is of the same type as the template parameter.
54+
template<typename TreeType>
55+
bool isType() const { return (this->type() == TreeType::treeType()); }
56+
5357
/// Return a pointer to a deep copy of this tree
5458
virtual TreeBase::Ptr copy() const = 0;
5559

openvdb/openvdb/unittest/TestTree.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2995,7 +2995,3 @@ TEST_F(TestTree, testInternalNode)
29952995
}
29962996
#endif
29972997
}
2998-
2999-
// Copyright (c) DreamWorks Animation LLC
3000-
// All rights reserved. This software is distributed under the
3001-
// Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )

0 commit comments

Comments
 (0)