44 std::is_trivial_v<T> && !std::is_pointer_v<T> &&
sizeof(T) <=
sizeof(
void*);
61 template <
typename T, std::enable_if_t<can_be_stored_literally_v<T>,
int> = 0>
73 template <
typename T, std::enable_if_t<can_be_stored_literally_v<T>,
int> = 0>
85 template <
typename T, std::enable_if_t<std::is_po
inter_v<T>,
int> = 0>
100 template <
typename T, std::enable_if_t<std::is_same_v<T,
void>,
int> = 0>
102 : m_container{
handle.m_raw_ptr}
103 , m_type{&typeid(T*)} {
104 static_assert(std::is_same_v<T, void>);
110 template <
typename T, std::enable_if_t<!std::is_same_v<T,
void>,
int> = 0>
112 : m_offset{
handle.m_offset}
113 , m_container{
handle.m_container_or_raw_ptr}
114 , m_type{&typeid(T*)}
115 , m_array_dim{
handle.m_array_dim}
116 , m_array_index{
handle.m_array_index} {
117 static_assert(!std::is_same_v<T, void>);
132 template <
typename T>
141 if (
typeid(T*) != *m_type) {
142 throw_error(
" cannot be converted to data_handle<" +
cxx_demangle(
typeid(T).
name()) +
145 if (m_offset.has_always_been_null()) {
155 if constexpr (!std::is_same_v<T, void>) {
156 if (!m_offset.was_once_valid()) {
160 return {m_offset,
static_cast<T* const*
>(m_container), m_array_dim, m_array_index};
181 template <
typename T>
183 if constexpr (std::is_pointer_v<T>) {
189 static_assert(can_be_stored_literally_v<T>,
190 "generic_data_handle can only hold non-pointer types that are trivial "
191 "and smaller than a pointer");
192 if (!m_offset.has_always_been_null()) {
194 " not possible for a handle [that was] in modern mode");
196 if (
typeid(T) != *m_type) {
197 throw_error(
" does not hold a literal value of type " +
201 std::memcpy(&ret, &m_container,
sizeof(T));
219 template <
typename T>
221 return m_type &&
typeid(T) == *m_type;
232 return !m_offset.has_always_been_null();
246 return m_type ?
cxx_demangle(m_type->name()) :
"typeless_null";
265 template <
typename T>
267 if (!m_offset.has_always_been_null()) {
269 "> cannot be called on a handle [that was] in modern mode");
276 }
else if (
typeid(T) != *m_type) {
277 throw_error(
" does not hold a literal value of type " +
280 return *
reinterpret_cast<T*
>(&m_container);
303 std::ostringstream oss{};
305 throw std::runtime_error(
std::move(oss).str());
314 std::type_info
const* m_type{};
316 int m_array_dim{1}, m_array_index{};
331 template <
typename T>
int cxx_demangle(const char *symbol, char **funcname, size_t *funcname_sz)
void move(Item *q1, Item *q2, Item *q3)
handle_interface< non_owning_identifier< storage > > handle
Non-owning handle to a Mechanism instance.
generic_data_handle promote_or_clear(generic_data_handle)
Try and promote a generic_data_handle wrapping a raw pointer.
data_handle< T > find_data_handle(T *ptr)
std::ostream & operator<<(std::ostream &os, generic_data_handle const &dh)
constexpr do_not_search_t do_not_search
Stable handle to a generic value.
Non-template stable handle to a generic value.
bool holds() const
Check if this handle refers to the specific type.
std::type_info const * m_type
static constexpr bool can_be_stored_literally_v
T & literal_value()
Obtain a reference to the literal value held by this handle.
bool refers_to_a_modern_data_structure() const
Check if this handle contains a data_handle<T> or just a literal.
void throw_error(std::string message) const
bool is_invalid_handle() const
Is the generic data handle a data_handle and invalid?
generic_data_handle(std::nullptr_t)
Construct a null data handle.
T get() const
Explicit conversion to any T.
generic_data_handle(do_not_search_t dns, T *raw_ptr)
generic_data_handle & operator=(T value)
Assign a small literal value to a generic data handle.
generic_data_handle(T value)
Construct a generic data handle that holds a small literal value.
generic_data_handle(data_handle< T > const &handle)
Wrap a data_handle<void> in a generic data handle.
std::string type_name() const
Return the demangled name of the type this handle refers to.
generic_data_handle()=default
Construct a null data handle.
A non-owning permutation-stable identifier for an entry in a container.