NEURON
|
Non-template stable handle to a generic value. More...
#include <generic_data_handle.hpp>
Public Member Functions | |
generic_data_handle ()=default | |
Construct a null data handle. More... | |
generic_data_handle (std::nullptr_t) | |
Construct a null data handle. More... | |
template<typename T , std::enable_if_t< can_be_stored_literally_v< T >, int > = 0> | |
generic_data_handle (T value) | |
Construct a generic data handle that holds a small literal value. More... | |
template<typename T , std::enable_if_t< can_be_stored_literally_v< T >, int > = 0> | |
generic_data_handle & | operator= (T value) |
Assign a small literal value to a generic data handle. More... | |
template<typename T , std::enable_if_t< std::is_pointer_v< T >, int > = 0> | |
generic_data_handle & | operator= (T value) |
Store a pointer inside this generic data handle. More... | |
template<typename T > | |
generic_data_handle (do_not_search_t dns, T *raw_ptr) | |
template<typename T , std::enable_if_t< std::is_same_v< T, void >, int > = 0> | |
generic_data_handle (data_handle< T > const &handle) | |
Wrap a data_handle<void> in a generic data handle. More... | |
template<typename T , std::enable_if_t<!std::is_same_v< T, void >, int > = 0> | |
generic_data_handle (data_handle< T > const &handle) | |
Wrap a data_handle<T != void> in a generic data handle. More... | |
template<typename T > | |
operator data_handle< T > () const | |
Create data_handle<T> from a generic data handle. More... | |
template<typename T > | |
T | get () const |
Explicit conversion to any T. More... | |
template<typename T > | |
bool | holds () const |
Check if this handle refers to the specific type. More... | |
bool | refers_to_a_modern_data_structure () const |
Check if this handle contains a data_handle<T> or just a literal. More... | |
std::string | type_name () const |
Return the demangled name of the type this handle refers to. More... | |
template<typename T > | |
T & | literal_value () |
Obtain a reference to the literal value held by this handle. More... | |
Private Member Functions | |
void | throw_error (std::string message) const |
Private Attributes | |
non_owning_identifier_without_container | m_offset {} |
void * | m_container {} |
std::type_info const * | m_type {} |
int | m_array_dim {1} |
int | m_array_index {} |
Static Private Attributes | |
template<typename T > | |
static constexpr bool | can_be_stored_literally_v |
Friends | |
std::ostream & | operator<< (std::ostream &os, generic_data_handle const &dh) |
Non-template stable handle to a generic value.
This is a type-erased version of data_handle<T>, with the additional feature that it can store values of POD types no larger than a pointer (typically int and float). It stores (at runtime) the type of the value it contains, and is therefore type-safe, but this increases sizeof(generic_data_handle) by 50% so it may be prudent to view this as useful for validation/debugging but not something to become too dependent on.
There are several states that instances of this class can be in:
wrapping a data handle<T> (m_type=&typeid(T*), m_container=the_container, m_offset=ptr_to_row)
Definition at line 37 of file generic_data_handle.hpp.
|
default |
Construct a null data handle.
|
inline |
Construct a null data handle.
Definition at line 52 of file generic_data_handle.hpp.
|
inlineexplicit |
Construct a generic data handle that holds a small literal value.
This is explicit to avoid things like operator<<(ostream&, generic_data_handle const&) being considered when printing values like size_t.
Definition at line 61 of file generic_data_handle.hpp.
|
inline |
Definition at line 90 of file generic_data_handle.hpp.
|
inline |
Wrap a data_handle<void> in a generic data handle.
Note that data_handle<void> is always wrapping a raw void* and is never in "modern" mode
Definition at line 100 of file generic_data_handle.hpp.
|
inline |
Wrap a data_handle<T != void> in a generic data handle.
Definition at line 110 of file generic_data_handle.hpp.
|
inline |
Explicit conversion to any T.
It might be interesting in future to explore dropping m_type in optimised builds, in which case we should aim to avoid predicating important logic on exceptions thrown by this function.
Something like static_cast<double*>(generic_handle) will work both if the Datum holds a literal double* and if it holds a data_handle<double>.
Definition at line 181 of file generic_data_handle.hpp.
|
inline |
Check if this handle refers to the specific type.
This could be a small, trivial type (e.g. T=int) or a pointer type (e.g. T=double*). holds<double*>() == true could either indicate that a data_handle<double> is held or that a literal double* is held.
It might be interesting in future to explore dropping m_type in optimised builds, in which case we should aim to avoid predicating important logic on this function.
Definition at line 219 of file generic_data_handle.hpp.
|
inline |
Obtain a reference to the literal value held by this handle.
Storing literal values is incompatible with storing data_handle<T>. If the handle stores data_handle<T> then calling this method throws an exception. If the handle is null, this sets the stored type to be T and returns a reference to it. If the handle already holds a literal value of type T then a reference to it is returned.
Note that, unlike converting to double*, literal_value<double*>() will fail if the handle contains data_handle<double>, as in that case there is no persistent double* that could be referred to.
It might be interesting in future to explore dropping m_type in optimised builds, in which case we should aim to avoid predicating important logic on exceptions thrown by this function.
Definition at line 265 of file generic_data_handle.hpp.
|
inlineexplicit |
Create data_handle<T> from a generic data handle.
The conversion will succeed, yielding a null data_handle<T>, if the generic data handle is null. If the generic data handle is not null then the conversion will succeed if the generic data handle actually holds a data_handle<T> or a literal T*.
It might be interesting in future to explore dropping m_type in optimised builds, in which case we should aim to avoid predicating important logic on exceptions thrown by this function.
Definition at line 132 of file generic_data_handle.hpp.
|
inline |
Assign a small literal value to a generic data handle.
This is important when generic_data_handle is used as the Datum type for "pointer" variables in MOD files.
Definition at line 73 of file generic_data_handle.hpp.
|
inline |
Store a pointer inside this generic data handle.
Explicit handling of pointer types (with redirection via data_handle<T>) ensures that some_generic_handle = some_ptr_to_T
promotes the raw T*
to a modern data_handle<T>
that is stable to permutation.
Definition at line 85 of file generic_data_handle.hpp.
|
inline |
Check if this handle contains a data_handle<T> or just a literal.
This should match static_cast<data_handle<T>>(generic_handle).refers_to_a_modern_data_structure() if T is correct. This will return true if we hold a data_handle that refers to a since-deleted row.
Definition at line 230 of file generic_data_handle.hpp.
|
inlineprivate |
Definition at line 284 of file generic_data_handle.hpp.
|
inline |
Return the demangled name of the type this handle refers to.
If the handle contains data_handle<T>, this will be T*. If a literal value or raw pointer is being wrapped, that possibly-pointer type will be returned.
It might be interesting in future to explore dropping m_type in optimised builds, in which case we should aim to avoid predicating important logic on this function.
Definition at line 244 of file generic_data_handle.hpp.
|
friend |
Definition at line 62 of file container.cpp.
|
staticconstexprprivate |
Definition at line 42 of file generic_data_handle.hpp.
|
private |
Definition at line 298 of file generic_data_handle.hpp.
|
private |
Definition at line 298 of file generic_data_handle.hpp.
|
private |
Definition at line 294 of file generic_data_handle.hpp.
|
private |
Definition at line 291 of file generic_data_handle.hpp.
|
private |
Definition at line 296 of file generic_data_handle.hpp.