mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-06 14:43:31 +00:00
Add CastableBase::To() overload with predicate
This allows for a more optimal way to filter the result of To(). Updated Type query functions to make use of it. Added tests. Change-Id: If3a65259345fbe6b92c6d367ab01fa718bb7cfee Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44463 Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
parent
b903aadcd2
commit
5106a0653c
@ -94,7 +94,7 @@ struct IsAnyOf;
|
|||||||
/// class `TO`
|
/// class `TO`
|
||||||
/// @param obj the object to test from
|
/// @param obj the object to test from
|
||||||
template <typename TO, typename FROM>
|
template <typename TO, typename FROM>
|
||||||
bool Is(FROM* obj) {
|
inline bool Is(FROM* obj) {
|
||||||
constexpr const bool downcast = std::is_base_of<FROM, TO>::value;
|
constexpr const bool downcast = std::is_base_of<FROM, TO>::value;
|
||||||
constexpr const bool upcast = std::is_base_of<TO, FROM>::value;
|
constexpr const bool upcast = std::is_base_of<TO, FROM>::value;
|
||||||
constexpr const bool nocast = std::is_same<FROM, TO>::value;
|
constexpr const bool nocast = std::is_same<FROM, TO>::value;
|
||||||
@ -111,6 +111,28 @@ 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 a valid pointer, and is of, or derives from the
|
||||||
|
/// class `TO`, and pred(const TO*) returns true
|
||||||
|
/// @param obj the object to test from
|
||||||
|
/// @param pred predicate function with signature `bool(const TO*)` called iff
|
||||||
|
/// object is of, or derives from the class `TO`.
|
||||||
|
template <typename TO, typename FROM, typename Pred>
|
||||||
|
inline bool Is(FROM* obj, Pred&& pred) {
|
||||||
|
constexpr const bool downcast = std::is_base_of<FROM, TO>::value;
|
||||||
|
constexpr const bool upcast = std::is_base_of<TO, FROM>::value;
|
||||||
|
constexpr const bool nocast = std::is_same<FROM, TO>::value;
|
||||||
|
static_assert(upcast || downcast || nocast, "impossible cast");
|
||||||
|
|
||||||
|
if (obj == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_type = upcast || nocast ||
|
||||||
|
obj->TypeInfo().Is(TypeInfo::Of<std::remove_const_t<TO>>());
|
||||||
|
|
||||||
|
return is_type && pred(static_cast<std::add_const_t<TO>*>(obj));
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns true if `obj` is of, or derives from any of the `TO`
|
/// @returns true if `obj` is of, or derives from any of the `TO`
|
||||||
/// classes.
|
/// classes.
|
||||||
/// @param obj the object to cast from
|
/// @param obj the object to cast from
|
||||||
@ -150,6 +172,15 @@ class CastableBase {
|
|||||||
return tint::Is<TO>(this);
|
return tint::Is<TO>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @returns true if this object is of, or derives from the class `TO` and
|
||||||
|
/// pred(const TO*) returns true
|
||||||
|
/// @param pred predicate function with signature `bool(const TO*)` called iff
|
||||||
|
/// object is of, or derives from the class `TO`.
|
||||||
|
template <typename TO, typename Pred>
|
||||||
|
inline bool Is(Pred&& pred) const {
|
||||||
|
return tint::Is<TO>(this, std::forward<Pred>(pred));
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns true if this object is of, or derives from any of the `TO`
|
/// @returns true if this object is of, or derives from any of the `TO`
|
||||||
/// classes.
|
/// classes.
|
||||||
template <typename... TO>
|
template <typename... TO>
|
||||||
@ -219,6 +250,16 @@ 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 the class `TO` and
|
||||||
|
/// pred(const TO*) returns true
|
||||||
|
/// @param pred predicate function with signature `bool(const TO*)` called iff
|
||||||
|
/// object is of, or derives from the class `TO`.
|
||||||
|
template <typename TO, typename Pred>
|
||||||
|
inline bool Is(Pred&& pred) const {
|
||||||
|
return tint::Is<TO>(static_cast<const CLASS*>(this),
|
||||||
|
std::forward<Pred>(pred));
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns true if this object is of, or derives from any of the `TO`
|
/// @returns true if this object is of, or derives from any of the `TO`
|
||||||
/// classes.
|
/// classes.
|
||||||
template <typename... TO>
|
template <typename... TO>
|
||||||
|
@ -73,6 +73,25 @@ TEST(CastableBase, Is) {
|
|||||||
ASSERT_TRUE(gecko->Is<Reptile>());
|
ASSERT_TRUE(gecko->Is<Reptile>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CastableBase, IsWithPredicate) {
|
||||||
|
std::unique_ptr<CastableBase> frog = std::make_unique<Frog>();
|
||||||
|
|
||||||
|
frog->Is<Animal>([&frog](const Animal* a) {
|
||||||
|
EXPECT_EQ(a, frog.get());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
ASSERT_TRUE((frog->Is<Animal>([](const Animal* a) { return true; })));
|
||||||
|
ASSERT_FALSE((frog->Is<Animal>([](const Animal* a) { return false; })));
|
||||||
|
|
||||||
|
// Predicate not called if cast is invalid
|
||||||
|
auto expect_not_called = [] { FAIL() << "Should not be called"; };
|
||||||
|
ASSERT_FALSE((frog->Is<Bear>([&](const Animal* a) {
|
||||||
|
expect_not_called();
|
||||||
|
return true;
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(CastableBase, IsAnyOf) {
|
TEST(CastableBase, IsAnyOf) {
|
||||||
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>();
|
||||||
@ -138,6 +157,25 @@ TEST(Castable, Is) {
|
|||||||
ASSERT_TRUE(gecko->Is<Reptile>());
|
ASSERT_TRUE(gecko->Is<Reptile>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Castable, IsWithPredicate) {
|
||||||
|
std::unique_ptr<Animal> frog = std::make_unique<Frog>();
|
||||||
|
|
||||||
|
frog->Is<Animal>([&frog](const Animal* a) {
|
||||||
|
EXPECT_EQ(a, frog.get());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
ASSERT_TRUE((frog->Is<Animal>([](const Animal* a) { return true; })));
|
||||||
|
ASSERT_FALSE((frog->Is<Animal>([](const Animal* a) { return false; })));
|
||||||
|
|
||||||
|
// Predicate not called if cast is invalid
|
||||||
|
auto expect_not_called = [] { FAIL() << "Should not be called"; };
|
||||||
|
ASSERT_FALSE((frog->Is<Bear>([&](const Animal* a) {
|
||||||
|
expect_not_called();
|
||||||
|
return true;
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(Castable, As) {
|
TEST(Castable, As) {
|
||||||
std::unique_ptr<Animal> frog = std::make_unique<Frog>();
|
std::unique_ptr<Animal> frog = std::make_unique<Frog>();
|
||||||
std::unique_ptr<Animal> bear = std::make_unique<Bear>();
|
std::unique_ptr<Animal> bear = std::make_unique<Bear>();
|
||||||
|
@ -79,11 +79,13 @@ bool Type::is_float_scalar() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Type::is_float_matrix() const {
|
bool Type::is_float_matrix() const {
|
||||||
return Is<Matrix>() && As<Matrix>()->type()->is_float_scalar();
|
return Is<Matrix>(
|
||||||
|
[](const Matrix* m) { return m->type()->is_float_scalar(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::is_float_vector() const {
|
bool Type::is_float_vector() const {
|
||||||
return Is<Vector>() && As<Vector>()->type()->is_float_scalar();
|
return Is<Vector>(
|
||||||
|
[](const Vector* v) { return v->type()->is_float_scalar(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::is_float_scalar_or_vector() const {
|
bool Type::is_float_scalar_or_vector() const {
|
||||||
@ -95,19 +97,19 @@ bool Type::is_integer_scalar() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Type::is_unsigned_integer_vector() const {
|
bool Type::is_unsigned_integer_vector() const {
|
||||||
return Is<Vector>() && As<Vector>()->type()->Is<U32>();
|
return Is<Vector>([](const Vector* v) { return v->type()->Is<U32>(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::is_signed_integer_vector() const {
|
bool Type::is_signed_integer_vector() const {
|
||||||
return Is<Vector>() && As<Vector>()->type()->Is<I32>();
|
return Is<Vector>([](const Vector* v) { return v->type()->Is<I32>(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::is_unsigned_scalar_or_vector() const {
|
bool Type::is_unsigned_scalar_or_vector() const {
|
||||||
return Is<U32>() || (Is<Vector>() && As<Vector>()->type()->Is<U32>());
|
return Is<U32>() || is_unsigned_integer_vector();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::is_signed_scalar_or_vector() const {
|
bool Type::is_signed_scalar_or_vector() const {
|
||||||
return Is<I32>() || (Is<Vector>() && As<Vector>()->type()->Is<I32>());
|
return Is<I32>() || is_signed_integer_vector();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::is_integer_scalar_or_vector() const {
|
bool Type::is_integer_scalar_or_vector() const {
|
||||||
@ -115,7 +117,7 @@ bool Type::is_integer_scalar_or_vector() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Type::is_bool_vector() const {
|
bool Type::is_bool_vector() const {
|
||||||
return Is<Vector>() && As<Vector>()->type()->Is<Bool>();
|
return Is<Vector>([](const Vector* v) { return v->type()->Is<Bool>(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::is_bool_scalar_or_vector() const {
|
bool Type::is_bool_scalar_or_vector() const {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user