rpcsx/rpcs3/util/typeindices.hpp
Nekotekina 567d23d856 Implement util/auto_typemap.hpp
Used in vm::block_t as an example.
2020-12-24 14:55:25 +03:00

146 lines
2.6 KiB
C++

#pragma once
namespace stx
{
template <typename Info>
class type_counter;
// Type information for given Info type, also serving as tag
template <typename Info>
class type_info final : public Info
{
// Current type id (starts from 0)
unsigned type = 0u - 1;
// Next typeinfo in linked list
type_info* next = nullptr;
type_info(Info info, decltype(sizeof(int))) noexcept;
friend type_counter<Info>;
public:
constexpr type_info() noexcept
: Info()
{
}
unsigned index() const
{
return type;
}
};
// Class for automatic type registration for given Info type
template <typename Info>
class type_counter final
{
// Dummy first element to simplify list filling logic
type_info<Info> first{};
// Linked list built at global initialization time
type_info<Info>* next = &first;
friend type_info<Info>;
public:
constexpr type_counter() noexcept = default;
unsigned count() const
{
return next->index() + 1;
}
class const_iterator
{
const type_info<Info>* ptr;
public:
const_iterator(const type_info<Info>* ptr)
: ptr(ptr)
{
}
const type_info<Info>& operator*() const
{
return *ptr;
}
const type_info<Info>* operator->() const
{
return ptr;
}
const_iterator& operator++()
{
ptr = ptr->next;
return *this;
}
const_iterator operator++(int)
{
const_iterator r = ptr;
ptr = ptr->next;
return r;
}
bool operator==(const const_iterator& r) const
{
return ptr == r.ptr;
}
bool operator!=(const const_iterator& r) const
{
return ptr != r.ptr;
}
};
const_iterator begin() const
{
return first.next;
}
const_iterator end() const
{
return nullptr;
}
// Global type info instance
template <typename T>
static inline const type_info<Info> type{Info::template make_typeinfo<T>(), sizeof(T)};
};
// Global typecounter instance
template <typename Info>
auto& typelist()
{
static type_counter<Info> typelist_v;
return typelist_v;
}
template <typename Info>
type_info<Info>::type_info(Info info, decltype(sizeof(int))) noexcept
: Info(info)
, type(typelist<Info>().count())
{
// Update linked list
auto& tl = typelist<Info>();
tl.next->next = this;
tl.next = this;
}
// Type index accessor
template <typename Info, typename T>
inline unsigned typeindex() noexcept
{
return type_counter<Info>::template type<T>.index();
}
// Type info accessor
template <typename Info, typename T>
inline const Info& typedata() noexcept
{
return type_counter<Info>::template type<T>;
}
}