68using TypeId = std::uint64_t;
 
   69static constexpr TypeId InvalidTypeId = UINT64_C(0);
 
   70static constexpr unsigned kDiscriminatorBits = 56;
 
   71static constexpr uint64_t kInnerTypeIdMask = (UINT64_C(1) << kDiscriminatorBits) - 1;
 
   72static constexpr uint64_t kHashDiscriminator = UINT64_C(0xFF);
 
   79    constexpr TypeNameHolder(
const char (&str)[N]) : str(&str[0]), length(N - 1) {}  
 
 
   91    return __PRETTY_FUNCTION__;
 
   92#elif defined(__GNUC__) 
   93    return __PRETTY_FUNCTION__;
 
   96#error "Unsupported compiler" 
  100static constexpr uint64_t FNV1a(
const char *str, 
size_t n,
 
  101                                uint64_t hash = UINT64_C(0xcbf29ce484222325)) {
 
  102    return n == 0 ? hash : FNV1a(str + 1, n - 1, UINT64_C(0x100000001b3) * (hash ^ str[0]));
 
  105static constexpr uint64_t FNV1a(TypeNameHolder str) { 
return FNV1a(str.str, str.length); }
 
  126template <
typename T, 
typename = 
void>
 
  128    static constexpr TypeId resolve() 
noexcept {
 
  130        uint64_t hash = FNV1a(typeNameProxy<T>());
 
  132        hash = (hash >> kDiscriminatorBits) ^ (hash & kInnerTypeIdMask);
 
  133        return (kHashDiscriminator << kDiscriminatorBits) | hash;
 
 
  140    static constexpr uint64_t resolve() 
noexcept {
 
  141        constexpr TypeId 
id = T::static_typeId();
 
 
  153static constexpr TypeId innerTypeId(TypeId 
id) { 
return id & kInnerTypeIdMask; }
 
  156static constexpr TypeId typeidDiscriminator(TypeId 
id) { 
return id >> kDiscriminatorBits; }
 
  159static constexpr TypeId combineTypeIdWithDiscriminator(TypeId discriminator, TypeId 
id) {
 
  160    return (discriminator << kDiscriminatorBits) | innerTypeId(
id);
 
  165template <
typename This, 
typename... Parents>
 
  167    using T = std::remove_const_t<std::remove_reference_t<This>>;
 
  169    static_assert((... && std::is_base_of_v<Parents, This>),
 
  170                  "One or more parents are not a base of this type.");
 
  172    static_assert((... && std::is_base_of_v<Base, Parents>),
 
  173                  "One or more parent hierarchies is not based on top of RTTI::Base.");
 
  175    static_assert(std::is_base_of_v<Base, This>,
 
  176                  "Invalid typeinfo requested, class is not based on top of RTTI::Base.");
 
  179        std::is_same_v<T *, 
decltype(T::rttiEnabledMarker(
nullptr))>,
 
  180        "Invalid typeinfo requested, class does not declare typeinfo via DECLARE_TYPEINFO.");
 
  182    [[nodiscard]] 
static constexpr TypeId id() 
noexcept {
 
  186    [[nodiscard]] 
static constexpr bool isA(TypeId typeId) 
noexcept {
 
  187        return (
id() == typeId) || (... || (Parents::TypeInfo::isA(typeId)));
 
  190    template <
typename T>
 
  191    [[nodiscard]] 
static const void *dyn_cast(TypeId typeId, 
const T *ptr) 
noexcept {
 
  192        if (
id() == typeId) 
return static_cast<const This *
>(ptr);
 
  194        std::array<
const void *, 
sizeof...(Parents)> ptrs = {
 
  195            Parents::TypeInfo::dyn_cast(typeId, ptr)...};
 
  198            std::find_if(ptrs.begin(), ptrs.end(), [](
const void *ptr) { return ptr != nullptr; });
 
  199        return (it != ptrs.end()) ? *it : 
nullptr;
 
 
  204    virtual ~Base() = 
default;
 
  208    [[nodiscard]] 
virtual TypeId 
typeId() const noexcept = 0;
 
  211    [[nodiscard]] virtual 
bool isA(TypeId 
typeId) const noexcept = 0;
 
  215    template <typename T>
 
  216    [[nodiscard]] 
bool is() const noexcept {
 
 
  225    template <
typename T>
 
  226    [[nodiscard]] T *
to() noexcept {
 
  227        return reinterpret_cast<T *
>(
const_cast<void *
>(toImpl(
TypeInfo<T>::id())));
 
 
  231    template <
typename T>
 
  232    [[nodiscard]] 
const T *
to() const noexcept {
 
 
  237    [[nodiscard]] 
virtual const void *toImpl(TypeId 
typeId) 
const noexcept = 0;
 
 
  259#define DECLARE_TYPEINFO(T, ...)                                                  \ 
  261    static constexpr RTTI::TypeId static_typeId() { return RTTI::InvalidTypeId; } \ 
  262    DECLARE_TYPEINFO_COMMON(T, ##__VA_ARGS__) 
  280#define DECLARE_TYPEINFO_WITH_TYPEID(T, Id, ...)                               \ 
  282    static constexpr RTTI::TypeId static_typeId() { return RTTI::TypeId(Id); } \ 
  283    DECLARE_TYPEINFO_COMMON(T, ##__VA_ARGS__) 
  291#define DECLARE_TYPEINFO_WITH_DISCRIMINATOR(T, Discriminator, InnerT, ...)         \ 
  293    static constexpr RTTI::TypeId static_typeId() {                                \ 
  294        return RTTI::combineTypeIdWithDiscriminator(RTTI::TypeId(Discriminator),   \ 
  295                                                    RTTI::TypeInfo<InnerT>::id()); \ 
  297    DECLARE_TYPEINFO_COMMON(T, ##__VA_ARGS__) 
  299#define DECLARE_TYPEINFO_COMMON(T, ...)                                                    \ 
  301    static constexpr T *rttiEnabledMarker(T *);                                            \ 
  302    using TypeInfo = RTTI::TypeInfo<T, ##__VA_ARGS__>;                                     \ 
  303    [[nodiscard]] RTTI::TypeId typeId() const noexcept override { return TypeInfo::id(); } \ 
  304    [[nodiscard]] bool isA(RTTI::TypeId typeId) const noexcept override {                  \ 
  305        return TypeInfo::isA(typeId);                                                      \ 
  309    [[nodiscard]] const void *toImpl(RTTI::TypeId typeId) const noexcept override {        \ 
  310        return TypeInfo::isA(typeId) ? TypeInfo::dyn_cast(typeId, this) : nullptr;         \ 
virtual bool isA(TypeId typeId) const noexcept=0
 
T * to() noexcept
Definition rtti.h:226
 
virtual TypeId typeId() const noexcept=0
 
const T * to() const noexcept
Same as to, but returns const pointer to T.
Definition rtti.h:232
 
bool is() const noexcept
Definition rtti.h:216