Add Castsable::IsAnyOf<T1, T2, ...>()

This makes it a little easier to check if an object is one of any of the
types provided. Updated Type query functions to make use of IsAnyOf.
Added tests.

Change-Id: I12ea62b32042b6675d998ab85b86f2fe15861330
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44462
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
Antonio Maiorano 2021-03-15 17:29:03 +00:00 committed by Commit Bot service account
parent 81a4753c38
commit a089a56c73
3 changed files with 75 additions and 3 deletions

View File

@ -83,6 +83,11 @@ struct TypeInfoOf {
/// The unique TypeInfo for the type T. /// The unique TypeInfo for the type T.
static const TypeInfo info; static const TypeInfo info;
}; };
// Forward declaration
template <typename TO_FIRST, typename... TO_REST>
struct IsAnyOf;
} // namespace detail } // namespace detail
/// @returns true if `obj` is a valid pointer, and is of, or derives from the /// @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<std::remove_const_t<TO>>()); return obj->TypeInfo().Is(TypeInfo::Of<std::remove_const_t<TO>>());
} }
/// @returns true if `obj` is of, or derives from any of the `TO`
/// classes.
/// @param obj the object to cast from
template <typename... TO, typename FROM>
inline bool IsAnyOf(FROM* obj) {
return detail::IsAnyOf<TO...>::Exec(obj);
}
/// @returns obj dynamically cast to the type `TO` or `nullptr` if /// @returns obj dynamically cast to the type `TO` or `nullptr` if
/// this object does not derive from `TO`. /// this object does not derive from `TO`.
/// @param obj the object to cast from /// @param obj the object to cast from
@ -137,6 +150,13 @@ class CastableBase {
return tint::Is<TO>(this); return tint::Is<TO>(this);
} }
/// @returns true if this object is of, or derives from any of the `TO`
/// classes.
template <typename... TO>
inline bool IsAnyOf() const {
return tint::IsAnyOf<TO...>(this);
}
/// @returns this object dynamically cast to the type `TO` or `nullptr` if /// @returns this object dynamically cast to the type `TO` or `nullptr` if
/// this object does not derive from `TO`. /// this object does not derive from `TO`.
template <typename TO> template <typename TO>
@ -199,6 +219,13 @@ class Castable : public BASE {
return tint::Is<TO>(static_cast<const CLASS*>(this)); return tint::Is<TO>(static_cast<const CLASS*>(this));
} }
/// @returns true if this object is of, or derives from any of the `TO`
/// classes.
template <typename... TO>
inline bool IsAnyOf() const {
return tint::IsAnyOf<TO...>(static_cast<const CLASS*>(this));
}
/// @returns this object dynamically cast to the type `TO` or `nullptr` if /// @returns this object dynamically cast to the type `TO` or `nullptr` if
/// this object does not derive from `TO`. /// this object does not derive from `TO`.
template <typename TO> template <typename TO>
@ -214,6 +241,30 @@ class Castable : public BASE {
} }
}; };
namespace detail {
/// Helper for Castable::IsAnyOf
template <typename TO_FIRST, typename... TO_REST>
struct IsAnyOf {
/// @param obj castable object to test
/// @returns true if `obj` is of, or derives from any of `[TO_FIRST,
/// ...TO_REST]`
template <typename FROM>
static bool Exec(FROM* obj) {
return Is<TO_FIRST>(obj) || IsAnyOf<TO_REST...>::Exec(obj);
}
};
/// Terminal specialization
template <typename TO>
struct IsAnyOf<TO> {
/// @param obj castable object to test
/// @returns true if `obj` is of, or derives from TO
template <typename FROM>
static bool Exec(FROM* obj) {
return Is<TO>(obj);
}
};
} // namespace detail
} // namespace tint } // namespace tint
TINT_CASTABLE_POP_DISABLE_WARNINGS(); TINT_CASTABLE_POP_DISABLE_WARNINGS();

View File

@ -73,6 +73,27 @@ TEST(CastableBase, Is) {
ASSERT_TRUE(gecko->Is<Reptile>()); ASSERT_TRUE(gecko->Is<Reptile>());
} }
TEST(CastableBase, IsAnyOf) {
std::unique_ptr<CastableBase> frog = std::make_unique<Frog>();
std::unique_ptr<CastableBase> bear = std::make_unique<Bear>();
std::unique_ptr<CastableBase> gecko = std::make_unique<Gecko>();
ASSERT_TRUE((frog->IsAnyOf<Animal, Mammal, Amphibian, Reptile>()));
ASSERT_TRUE((frog->IsAnyOf<Mammal, Amphibian>()));
ASSERT_TRUE((frog->IsAnyOf<Amphibian, Reptile>()));
ASSERT_FALSE((frog->IsAnyOf<Mammal, Reptile>()));
ASSERT_TRUE((bear->IsAnyOf<Animal, Mammal, Amphibian, Reptile>()));
ASSERT_TRUE((bear->IsAnyOf<Mammal, Amphibian>()));
ASSERT_TRUE((bear->IsAnyOf<Mammal, Reptile>()));
ASSERT_FALSE((bear->IsAnyOf<Amphibian, Reptile>()));
ASSERT_TRUE((gecko->IsAnyOf<Animal, Mammal, Amphibian, Reptile>()));
ASSERT_TRUE((gecko->IsAnyOf<Mammal, Reptile>()));
ASSERT_TRUE((gecko->IsAnyOf<Amphibian, Reptile>()));
ASSERT_FALSE((gecko->IsAnyOf<Mammal, Amphibian>()));
}
TEST(CastableBase, As) { TEST(CastableBase, As) {
std::unique_ptr<CastableBase> frog = std::make_unique<Frog>(); std::unique_ptr<CastableBase> frog = std::make_unique<Frog>();
std::unique_ptr<CastableBase> bear = std::make_unique<Bear>(); std::unique_ptr<CastableBase> bear = std::make_unique<Bear>();

View File

@ -71,7 +71,7 @@ Type* Type::UnwrapAll() {
} }
bool Type::is_scalar() const { bool Type::is_scalar() const {
return is_float_scalar() || is_integer_scalar() || Is<Bool>(); return IsAnyOf<F32, U32, I32, Bool>();
} }
bool Type::is_float_scalar() const { bool Type::is_float_scalar() const {
@ -91,7 +91,7 @@ bool Type::is_float_scalar_or_vector() const {
} }
bool Type::is_integer_scalar() const { bool Type::is_integer_scalar() const {
return Is<U32>() || Is<I32>(); return IsAnyOf<U32, I32>();
} }
bool Type::is_unsigned_integer_vector() const { bool Type::is_unsigned_integer_vector() const {
@ -123,7 +123,7 @@ bool Type::is_bool_scalar_or_vector() const {
} }
bool Type::is_handle() const { bool Type::is_handle() const {
return Is<type::Sampler>() || Is<type::Texture>(); return IsAnyOf<Sampler, Texture>();
} }
} // namespace type } // namespace type