memgraph/src/utils/typeinfo.hpp

62 lines
2.0 KiB
C++
Raw Normal View History

/// @file
#pragma once
#include <cstdint>
namespace utils {
/// Type information on a C++ type.
///
/// You should embed this structure as a static constant member `kType` and make
/// sure you generate a unique ID for it. Also, if your type has inheritance,
/// you may want to add a `virtual utils::TypeInfo GetType();` method to get the
/// runtime type.
struct TypeInfo {
/// Unique ID for the type.
uint64_t id;
/// Pretty name of the type.
const char *name;
/// `TypeInfo *` for superclass of this type.
/// Multiple inheritance is not supported.
const TypeInfo *superclass{nullptr};
};
inline bool operator==(const TypeInfo &a, const TypeInfo &b) { return a.id == b.id; }
inline bool operator!=(const TypeInfo &a, const TypeInfo &b) { return a.id != b.id; }
inline bool operator<(const TypeInfo &a, const TypeInfo &b) { return a.id < b.id; }
inline bool operator<=(const TypeInfo &a, const TypeInfo &b) { return a.id <= b.id; }
inline bool operator>(const TypeInfo &a, const TypeInfo &b) { return a.id > b.id; }
inline bool operator>=(const TypeInfo &a, const TypeInfo &b) { return a.id >= b.id; }
/// Return true if `a` is subtype or the same type as `b`.
inline bool IsSubtype(const TypeInfo &a, const TypeInfo &b) {
if (a == b) return true;
const TypeInfo *super_a = a.superclass;
while (super_a) {
if (*super_a == b) return true;
super_a = super_a->superclass;
}
return false;
}
template <class T>
bool IsSubtype(const T &a, const TypeInfo &b) {
return IsSubtype(a.GetTypeInfo(), b);
}
/// Downcast `a` to `TDerived` using static_cast.
///
/// If `a` is `nullptr` or `TBase` is not a subtype of `TDerived`, then a
/// `nullptr` is returned.
///
/// This downcast is ill-formed if TBase is ambiguous, inaccessible, or virtual
/// base (or a base of a virtual base) of TDerived.
template <class TDerived, class TBase>
TDerived *Downcast(TBase *a) {
if (!a) return nullptr;
if (IsSubtype(*a, TDerived::kType)) return static_cast<TDerived *>(a);
return nullptr;
}
} // namespace utils