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 P4::RTTI::TypeId static_typeId() { return P4::RTTI::InvalidTypeId; } \
262 DECLARE_TYPEINFO_COMMON(T, ##__VA_ARGS__)
280#define DECLARE_TYPEINFO_WITH_TYPEID(T, Id, ...) \
282 static constexpr P4::RTTI::TypeId static_typeId() { return P4::RTTI::TypeId(Id); } \
283 DECLARE_TYPEINFO_COMMON(T, ##__VA_ARGS__)
291#define DECLARE_TYPEINFO_WITH_DISCRIMINATOR(T, Discriminator, InnerT, ...) \
293 static constexpr P4::RTTI::TypeId static_typeId() { \
294 return P4::RTTI::combineTypeIdWithDiscriminator(P4::RTTI::TypeId(Discriminator), \
295 P4::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 = P4::RTTI::TypeInfo<T, ##__VA_ARGS__>; \
303 [[nodiscard]] P4::RTTI::TypeId typeId() const noexcept override { return TypeInfo::id(); } \
304 [[nodiscard]] bool isA(P4::RTTI::TypeId typeId) const noexcept override { \
305 return TypeInfo::isA(typeId); \
309 [[nodiscard]] const void *toImpl(P4::RTTI::TypeId typeId) const noexcept override { \
310 return TypeInfo::isA(typeId) ? TypeInfo::dyn_cast(typeId, this) : nullptr; \
T * to() noexcept
Definition rtti.h:226
bool is() const noexcept
Definition rtti.h:216
virtual TypeId typeId() const noexcept=0
const T * to() const noexcept
Same as to, but returns const pointer to T.
Definition rtti.h:232
virtual bool isA(TypeId typeId) const noexcept=0