diff --git a/src/castable.h b/src/castable.h index 072872ab22..0dada0d953 100644 --- a/src/castable.h +++ b/src/castable.h @@ -83,6 +83,11 @@ struct TypeInfoOf { /// The unique TypeInfo for the type T. static const TypeInfo info; }; + +// Forward declaration +template +struct IsAnyOf; + } // namespace detail /// @returns true if `obj` is a valid pointer, and is of, or derives from the @@ -106,6 +111,14 @@ bool Is(FROM* obj) { return obj->TypeInfo().Is(TypeInfo::Of>()); } +/// @returns true if `obj` is of, or derives from any of the `TO` +/// classes. +/// @param obj the object to cast from +template +inline bool IsAnyOf(FROM* obj) { + return detail::IsAnyOf::Exec(obj); +} + /// @returns obj dynamically cast to the type `TO` or `nullptr` if /// this object does not derive from `TO`. /// @param obj the object to cast from @@ -137,6 +150,13 @@ class CastableBase { return tint::Is(this); } + /// @returns true if this object is of, or derives from any of the `TO` + /// classes. + template + inline bool IsAnyOf() const { + return tint::IsAnyOf(this); + } + /// @returns this object dynamically cast to the type `TO` or `nullptr` if /// this object does not derive from `TO`. template @@ -199,6 +219,13 @@ class Castable : public BASE { return tint::Is(static_cast(this)); } + /// @returns true if this object is of, or derives from any of the `TO` + /// classes. + template + inline bool IsAnyOf() const { + return tint::IsAnyOf(static_cast(this)); + } + /// @returns this object dynamically cast to the type `TO` or `nullptr` if /// this object does not derive from `TO`. template @@ -214,6 +241,30 @@ class Castable : public BASE { } }; +namespace detail { +/// Helper for Castable::IsAnyOf +template +struct IsAnyOf { + /// @param obj castable object to test + /// @returns true if `obj` is of, or derives from any of `[TO_FIRST, + /// ...TO_REST]` + template + static bool Exec(FROM* obj) { + return Is(obj) || IsAnyOf::Exec(obj); + } +}; +/// Terminal specialization +template +struct IsAnyOf { + /// @param obj castable object to test + /// @returns true if `obj` is of, or derives from TO + template + static bool Exec(FROM* obj) { + return Is(obj); + } +}; +} // namespace detail + } // namespace tint TINT_CASTABLE_POP_DISABLE_WARNINGS(); diff --git a/src/castable_test.cc b/src/castable_test.cc index 333075766b..05f5e4ab11 100644 --- a/src/castable_test.cc +++ b/src/castable_test.cc @@ -73,6 +73,27 @@ TEST(CastableBase, Is) { ASSERT_TRUE(gecko->Is()); } +TEST(CastableBase, IsAnyOf) { + std::unique_ptr frog = std::make_unique(); + std::unique_ptr bear = std::make_unique(); + std::unique_ptr gecko = std::make_unique(); + + ASSERT_TRUE((frog->IsAnyOf())); + ASSERT_TRUE((frog->IsAnyOf())); + ASSERT_TRUE((frog->IsAnyOf())); + ASSERT_FALSE((frog->IsAnyOf())); + + ASSERT_TRUE((bear->IsAnyOf())); + ASSERT_TRUE((bear->IsAnyOf())); + ASSERT_TRUE((bear->IsAnyOf())); + ASSERT_FALSE((bear->IsAnyOf())); + + ASSERT_TRUE((gecko->IsAnyOf())); + ASSERT_TRUE((gecko->IsAnyOf())); + ASSERT_TRUE((gecko->IsAnyOf())); + ASSERT_FALSE((gecko->IsAnyOf())); +} + TEST(CastableBase, As) { std::unique_ptr frog = std::make_unique(); std::unique_ptr bear = std::make_unique(); diff --git a/src/type/type.cc b/src/type/type.cc index 39f309c2c8..ecd79eaeab 100644 --- a/src/type/type.cc +++ b/src/type/type.cc @@ -71,7 +71,7 @@ Type* Type::UnwrapAll() { } bool Type::is_scalar() const { - return is_float_scalar() || is_integer_scalar() || Is(); + return IsAnyOf(); } bool Type::is_float_scalar() const { @@ -91,7 +91,7 @@ bool Type::is_float_scalar_or_vector() const { } bool Type::is_integer_scalar() const { - return Is() || Is(); + return IsAnyOf(); } bool Type::is_unsigned_integer_vector() const { @@ -123,7 +123,7 @@ bool Type::is_bool_scalar_or_vector() const { } bool Type::is_handle() const { - return Is() || Is(); + return IsAnyOf(); } } // namespace type