Pull Is() out of castable and into a new TypeInfo
Allows you to query type inheritance without having an instance of the type. Also add TypeInfo::name. Helpful for decent error messages. Strings can be removed from NDEBUG builds if we consider them too large. Change-Id: Ie501b37f46e63d956cc020f8c9b68e91737472f0 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/42920 Reviewed-by: Antonio Maiorano <amaiorano@google.com> Reviewed-by: James Price <jrprice@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
5cfd4f5a07
commit
e879143801
|
@ -161,6 +161,7 @@ function(tint_default_compile_options TARGET)
|
||||||
-Wno-format-pedantic
|
-Wno-format-pedantic
|
||||||
-Wno-return-std-move-in-c++11
|
-Wno-return-std-move-in-c++11
|
||||||
-Wno-unknown-warning-option
|
-Wno-unknown-warning-option
|
||||||
|
-Wno-undefined-var-template
|
||||||
-Weverything
|
-Weverything
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -14,12 +14,23 @@
|
||||||
|
|
||||||
#include "src/castable.h"
|
#include "src/castable.h"
|
||||||
|
|
||||||
TINT_INSTANTIATE_CLASS_ID(tint::CastableBase);
|
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
|
||||||
bool CastableBase::Is(ClassID id) const {
|
/// The unique TypeInfo for the CastableBase type
|
||||||
return ClassID::Of<CastableBase>() == id;
|
/// @return doxygen-thinks-this-static-field-is-a-function :(
|
||||||
|
template <>
|
||||||
|
const TypeInfo detail::TypeInfoOf<CastableBase>::info{
|
||||||
|
nullptr,
|
||||||
|
"CastableBase",
|
||||||
|
};
|
||||||
|
|
||||||
|
bool TypeInfo::Is(const TypeInfo& typeinfo) const {
|
||||||
|
for (auto* ti = this; ti != nullptr; ti = ti->base) {
|
||||||
|
if (ti == &typeinfo) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
111
src/castable.h
111
src/castable.h
|
@ -22,57 +22,49 @@
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
|
||||||
class ClassID;
|
namespace detail {
|
||||||
|
template <typename T>
|
||||||
|
struct TypeInfoOf;
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
/// Helper macro to instantiate the TypeInfo<T> template for `CLASS`.
|
/// Helper macro to instantiate the TypeInfo<T> template for `CLASS`.
|
||||||
#define TINT_INSTANTIATE_CLASS_ID(CLASS) \
|
#define TINT_INSTANTIATE_CLASS_ID(CLASS) \
|
||||||
template <> \
|
template <> \
|
||||||
const char tint::UniqueToken<CLASS>::token = 0; \
|
const tint::TypeInfo tint::detail::TypeInfoOf<CLASS>::info { \
|
||||||
template <> \
|
&tint::detail::TypeInfoOf<CLASS::TrueBase>::info, #CLASS, \
|
||||||
const uintptr_t tint::TypeInfo<CLASS>::unique_id = \
|
}
|
||||||
reinterpret_cast<uintptr_t>(&tint::UniqueToken<CLASS>::token)
|
|
||||||
|
|
||||||
/// TypeInfo holds type information for the type T.
|
/// TypeInfo holds type information for a Castable type.
|
||||||
|
struct TypeInfo {
|
||||||
|
/// The base class of this type.
|
||||||
|
const TypeInfo* base;
|
||||||
|
/// The type name
|
||||||
|
const char* name;
|
||||||
|
|
||||||
|
/// @param type the test type info
|
||||||
|
/// @returns true if the class with this TypeInfo is of, or derives from the
|
||||||
|
/// class with the given TypeInfo.
|
||||||
|
bool Is(const tint::TypeInfo& type) const;
|
||||||
|
|
||||||
|
/// @returns the static TypeInfo for the type T
|
||||||
|
template <typename T>
|
||||||
|
static const TypeInfo& Of() {
|
||||||
|
return detail::TypeInfoOf<T>::info;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/// TypeInfoOf contains a single TypeInfo field for the type T.
|
||||||
/// TINT_INSTANTIATE_CLASS_ID() must be defined in a .cpp file for each type
|
/// TINT_INSTANTIATE_CLASS_ID() must be defined in a .cpp file for each type
|
||||||
/// `T`.
|
/// `T`.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct TypeInfo {
|
struct TypeInfoOf {
|
||||||
/// The unique identifier for the type T.
|
/// The unique TypeInfo for the type T.
|
||||||
static const uintptr_t unique_id;
|
static const TypeInfo info;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// UniqueToken holds a single static const char, which is uniquely declared for
|
} // namespace detail
|
||||||
/// each specialization of the template class.
|
|
||||||
/// Use by TINT_INSTANTIATE_CLASS_ID() to generate a unique pointer, which is in
|
|
||||||
/// turn used to generate TypeInfo<T>::unique_id.
|
|
||||||
template <typename T>
|
|
||||||
struct UniqueToken {
|
|
||||||
/// A dummy static variable that is unique for the type T.
|
|
||||||
static const char token;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// ClassID represents a unique, comparable identifier for a C++ type.
|
|
||||||
class ClassID {
|
|
||||||
public:
|
|
||||||
/// @returns the unique ClassID for the type T.
|
|
||||||
template <typename T>
|
|
||||||
static inline ClassID Of() {
|
|
||||||
return ClassID(TypeInfo<T>::unique_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Equality operator
|
|
||||||
/// @param rhs the ClassID to compare against
|
|
||||||
/// @returns true if this ClassID is equal to `rhs`
|
|
||||||
inline bool operator==(const ClassID& rhs) const { return id == rhs.id; }
|
|
||||||
|
|
||||||
/// @return the unique numerical identifier of this ClassID
|
|
||||||
inline uintptr_t ID() const { return id; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
inline explicit ClassID(uintptr_t v) : id(v) {}
|
|
||||||
|
|
||||||
const uintptr_t id;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// CastableBase is the base class for all Castable objects.
|
/// CastableBase is the base class for all Castable objects.
|
||||||
/// It is not encouraged to directly derive from CastableBase without using the
|
/// It is not encouraged to directly derive from CastableBase without using the
|
||||||
|
@ -88,10 +80,8 @@ class CastableBase {
|
||||||
|
|
||||||
virtual ~CastableBase() = default;
|
virtual ~CastableBase() = default;
|
||||||
|
|
||||||
/// @returns true if this object is of, or derives from a class with the
|
/// @returns the TypeInfo of the object
|
||||||
/// ClassID `id`.
|
virtual const tint::TypeInfo& TypeInfo() const = 0;
|
||||||
/// @param id the ClassID to test for
|
|
||||||
virtual bool Is(ClassID id) const;
|
|
||||||
|
|
||||||
/// @returns true if this object is of, or derives from the class `TO`
|
/// @returns true if this object is of, or derives from the class `TO`
|
||||||
template <typename TO>
|
template <typename TO>
|
||||||
|
@ -106,7 +96,7 @@ class CastableBase {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Is(ClassID::Of<TO>());
|
return TypeInfo().Is(TypeInfo::Of<TO>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns this object dynamically cast to the type `TO` or `nullptr` if
|
/// @returns this object dynamically cast to the type `TO` or `nullptr` if
|
||||||
|
@ -157,11 +147,12 @@ class Castable : public BASE {
|
||||||
/// use Base in the `CLASS` constructor.
|
/// use Base in the `CLASS` constructor.
|
||||||
using Base = Castable;
|
using Base = Castable;
|
||||||
|
|
||||||
/// @returns true if this object is of, or derives from a class with the
|
/// A type alias for `BASE`.
|
||||||
/// ClassID `id`.
|
using TrueBase = BASE;
|
||||||
/// @param id the ClassID to test for
|
|
||||||
inline bool Is(ClassID id) const override {
|
/// @returns the TypeInfo of the object
|
||||||
return ClassID::Of<CLASS>() == id || BASE::Is(id);
|
const tint::TypeInfo& TypeInfo() const override {
|
||||||
|
return TypeInfo::Of<CLASS>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns true if this object is of, or derives from the class `TO`
|
/// @returns true if this object is of, or derives from the class `TO`
|
||||||
|
@ -177,7 +168,7 @@ class Castable : public BASE {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Is(ClassID::Of<TO>());
|
return TypeInfo().Is(TypeInfo::Of<TO>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns this object dynamically cast to the type `TO` or `nullptr` if
|
/// @returns this object dynamically cast to the type `TO` or `nullptr` if
|
||||||
|
@ -209,20 +200,4 @@ inline TO* As(FROM* obj) {
|
||||||
|
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
||||||
namespace std {
|
|
||||||
|
|
||||||
/// Custom std::hash specialization for tint::ClassID so ClassID can be used as
|
|
||||||
/// keys for std::unordered_map and std::unordered_set.
|
|
||||||
template <>
|
|
||||||
class hash<tint::ClassID> {
|
|
||||||
public:
|
|
||||||
/// @param id the ClassID to hash
|
|
||||||
/// @return the ClassID's internal numerical identifier
|
|
||||||
inline std::size_t operator()(const tint::ClassID& id) const {
|
|
||||||
return static_cast<std::size_t>(id.ID());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
#endif // SRC_CASTABLE_H_
|
#endif // SRC_CASTABLE_H_
|
||||||
|
|
|
@ -67,14 +67,14 @@ class DataMap {
|
||||||
void Put(std::unique_ptr<T>&& data) {
|
void Put(std::unique_ptr<T>&& data) {
|
||||||
static_assert(std::is_base_of<Data, T>::value,
|
static_assert(std::is_base_of<Data, T>::value,
|
||||||
"T does not derive from Data");
|
"T does not derive from Data");
|
||||||
map_[ClassID::Of<T>()] = std::move(data);
|
map_[&TypeInfo::Of<T>()] = std::move(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns a pointer to the Data placed into the DataMap with a call to
|
/// @returns a pointer to the Data placed into the DataMap with a call to
|
||||||
/// Put()
|
/// Put()
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T const* Get() const {
|
T const* Get() const {
|
||||||
auto it = map_.find(ClassID::Of<T>());
|
auto it = map_.find(&TypeInfo::Of<T>());
|
||||||
if (it == map_.end()) {
|
if (it == map_.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ class DataMap {
|
||||||
PutAll(std::forward<Tn>(remainder)...);
|
PutAll(std::forward<Tn>(remainder)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<ClassID, std::unique_ptr<Data>> map_;
|
std::unordered_map<const TypeInfo*, std::unique_ptr<Data>> map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Interface for Program transforms
|
/// Interface for Program transforms
|
||||||
|
|
Loading…
Reference in New Issue