From 81a4753c388f4896dce4f9e51d338a01c85867fc Mon Sep 17 00:00:00 2001 From: Antonio Maiorano Date: Mon, 15 Mar 2021 17:20:51 +0000 Subject: [PATCH] Castable: factor out Is and As to free standing functions These can now also be called with nullptr and will return false or nullptr respectively. Change-Id: I5fcf292503dd718f8d3771c7c39c204ce03ff4f7 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44461 Reviewed-by: Ben Clayton Commit-Queue: Antonio Maiorano --- src/castable.h | 74 ++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/src/castable.h b/src/castable.h index 956f4f65d0..072872ab22 100644 --- a/src/castable.h +++ b/src/castable.h @@ -83,9 +83,37 @@ struct TypeInfoOf { /// The unique TypeInfo for the type T. static const TypeInfo info; }; - } // namespace detail +/// @returns true if `obj` is a valid pointer, and is of, or derives from the +/// class `TO` +/// @param obj the object to test from +template +bool Is(FROM* obj) { + constexpr const bool downcast = std::is_base_of::value; + constexpr const bool upcast = std::is_base_of::value; + constexpr const bool nocast = std::is_same::value; + static_assert(upcast || downcast || nocast, "impossible cast"); + + if (obj == nullptr) { + return false; + } + + if (upcast || nocast) { + return true; + } + + return obj->TypeInfo().Is(TypeInfo::Of>()); +} + +/// @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 +template +inline TO* As(FROM* obj) { + return Is(obj) ? static_cast(obj) : nullptr; +} + /// CastableBase is the base class for all Castable objects. /// It is not encouraged to directly derive from CastableBase without using the /// Castable helper template. @@ -106,31 +134,21 @@ class CastableBase { /// @returns true if this object is of, or derives from the class `TO` template inline bool Is() const { - using FROM = CastableBase; - constexpr const bool downcast = std::is_base_of::value; - constexpr const bool upcast = std::is_base_of::value; - constexpr const bool nocast = std::is_same::value; - static_assert(upcast || downcast || nocast, "impossible cast"); - - if (upcast || nocast) { - return true; - } - - return TypeInfo().Is(TypeInfo::Of()); + return tint::Is(this); } /// @returns this object dynamically cast to the type `TO` or `nullptr` if /// this object does not derive from `TO`. template inline TO* As() { - return Is() ? static_cast(this) : nullptr; + return tint::As(this); } /// @returns this object dynamically cast to the type `TO` or `nullptr` if /// this object does not derive from `TO`. template inline const TO* As() const { - return Is() ? static_cast(this) : nullptr; + return tint::As(this); } protected: @@ -178,46 +196,24 @@ class Castable : public BASE { /// @returns true if this object is of, or derives from the class `TO` template inline bool Is() const { - using FROM = Castable; - constexpr const bool downcast = std::is_base_of::value; - constexpr const bool upcast = std::is_base_of::value; - constexpr const bool nocast = std::is_same::value; - static_assert(upcast || downcast || nocast, "impossible cast"); - - if (upcast || nocast) { - return true; - } - - return TypeInfo().Is(TypeInfo::Of()); + return tint::Is(static_cast(this)); } /// @returns this object dynamically cast to the type `TO` or `nullptr` if /// this object does not derive from `TO`. template inline TO* As() { - return Is() ? static_cast(this) : nullptr; + return tint::As(this); } /// @returns this object dynamically cast to the type `TO` or `nullptr` if /// this object does not derive from `TO`. template inline const TO* As() const { - return Is() ? static_cast(this) : nullptr; + return tint::As(this); } }; -/// As() dynamically casts `obj` to the target type `TO`. -/// @returns the cast object, or nullptr if `obj` is `nullptr` or not of the -/// type `TO`. -/// @param obj the object to cast -template -inline TO* As(FROM* obj) { - if (obj == nullptr) { - return nullptr; - } - return obj->template As(); -} - } // namespace tint TINT_CASTABLE_POP_DISABLE_WARNINGS();