xo-reflect: allow TypeDescr without .native_typeinfo
This commit is contained in:
parent
515cedf160
commit
7243939916
5 changed files with 83 additions and 13 deletions
|
|
@ -27,7 +27,7 @@ or equivalently
|
||||||
$ git clone git@github.com:Rconybea/xo-reflect.git
|
$ git clone git@github.com:Rconybea/xo-reflect.git
|
||||||
```
|
```
|
||||||
|
|
||||||
### build + install xo-reflect
|
### build + install `xo-reflect`
|
||||||
```
|
```
|
||||||
$ xo-build --configure --build --install xo-reflect
|
$ xo-build --configure --build --install xo-reflect
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,15 @@ namespace xo {
|
||||||
return retval_td;
|
return retval_td;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** given address @p src_address of a value with type described by @p src,
|
||||||
|
* return typed pointer of type @tparam T, provided that @p src_td
|
||||||
|
* actually describes @tparam T. Otherwise returns nullptr
|
||||||
|
**/
|
||||||
|
template <typename T>
|
||||||
|
static T * recover_native(TypeDescr src_td, void * src_address) {
|
||||||
|
return TaggedPtr(src_td, src_address).recover_native<T>();
|
||||||
|
}
|
||||||
|
|
||||||
/* Use:
|
/* Use:
|
||||||
* T * xyz = ...;
|
* T * xyz = ...;
|
||||||
* TaggedPtr xyz_tp = Reflect::make_tp(xyz);
|
* TaggedPtr xyz_tp = Reflect::make_tp(xyz);
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ namespace xo {
|
||||||
* to refer to a T-instance; otherwise nullptr
|
* to refer to a T-instance; otherwise nullptr
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T * recover_native() const { return this->td_->recover_native<T>(this->address_); }
|
T * recover_native() const { return this->td_->recover_native2<T>(this->td_, this->address_); }
|
||||||
|
|
||||||
uint32_t n_child() const {
|
uint32_t n_child() const {
|
||||||
return this->td_->n_child(this->address_);
|
return this->td_->n_child(this->address_);
|
||||||
|
|
|
||||||
|
|
@ -149,28 +149,66 @@ namespace xo {
|
||||||
static void print_reflected_types(std::ostream & os);
|
static void print_reflected_types(std::ostream & os);
|
||||||
|
|
||||||
TypeId id() const { return id_; }
|
TypeId id() const { return id_; }
|
||||||
std::type_info const * typeinfo() const { return typeinfo_; }
|
std::type_info const * native_typeinfo() const { return native_typeinfo_; }
|
||||||
std::string_view const & canonical_name() const { return canonical_name_; }
|
std::string_view const & canonical_name() const { return canonical_name_; }
|
||||||
std::string_view const & short_name() const { return short_name_; }
|
std::string_view const & short_name() const { return short_name_; }
|
||||||
bool complete_flag() const { return complete_flag_; }
|
bool complete_flag() const { return complete_flag_; }
|
||||||
TypeDescrExtra * tdextra() const { return tdextra_.get(); }
|
TypeDescrExtra * tdextra() const { return tdextra_.get(); }
|
||||||
Metatype metatype() const { return tdextra_->metatype(); }
|
Metatype metatype() const { return tdextra_->metatype(); }
|
||||||
|
|
||||||
/* true iff the type represented by *this is the same as the type T.
|
/* true iff the type represented by *this is the same as the type
|
||||||
|
* represented by T.
|
||||||
*
|
*
|
||||||
* Warning: comparing typeinfo address can give false negatives.
|
* Warning: comparing typeinfo address can give false negatives.
|
||||||
* suspect this is caused by problems coalescing linker symbols
|
* suspect this is caused by problems coalescing linker symbols
|
||||||
* in the clang toolchain.
|
* in the clang toolchain.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
[[deprecated]]
|
||||||
bool is_native() const {
|
bool is_native() const {
|
||||||
return ((this->typeinfo() == &typeid(T))
|
if (this->native_typeinfo()) {
|
||||||
|| (this->typeinfo()->hash_code() == typeid(T).hash_code())
|
/* reminder: typeid(T).name() is 'interesting' but not intended
|
||||||
|| (this->typeinfo()->name() == typeid(T).name()));
|
* to be human-readable. It's not how compiler labels
|
||||||
|
* a type for a human reader
|
||||||
|
*/
|
||||||
|
return ((this->native_typeinfo() == &typeid(T))
|
||||||
|
|| (this->native_typeinfo()->hash_code() == typeid(T).hash_code())
|
||||||
|
|| (this->native_typeinfo()->name() == typeid(T).name()));
|
||||||
|
} else {
|
||||||
|
/** if this type was established via Reflect::require<T1>(),
|
||||||
|
* then .canonical_name is computed by type_name<T>()
|
||||||
|
*
|
||||||
|
* (see demangle.hh in xo-refcnt, which post-processes __PRETTY_FUNCTION__
|
||||||
|
* or __FUNCSIG__)
|
||||||
|
*
|
||||||
|
* To manually construct an equivalent type,
|
||||||
|
* it's necessary to:
|
||||||
|
* 1. construct a unique and unambiguous canonical name for the type
|
||||||
|
* 2. be aware that type will only be recognized as equivalent to
|
||||||
|
* a natively-reflected type if canonical name matches exactly.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/** FOR NOW: give up. **/
|
||||||
|
throw std::runtime_error("TypeDescrBase::is_native: not implemented for manually-constructed TypeDescr objects. Prefer is_native2()");
|
||||||
|
}
|
||||||
} /*is_native*/
|
} /*is_native*/
|
||||||
|
|
||||||
/* safe downcast -- like dynamic_cast<>, but does not require a source type */
|
/** safe downcast -- like dynamic_cast<>, but does not require a source type.
|
||||||
|
*
|
||||||
|
* TODO: need variation on this to correctly-handle function types,
|
||||||
|
* since for exampple cast from void* -> void (*)() is not allowed
|
||||||
|
*
|
||||||
|
* WARNING: relies on deprecated is_native<T>(). Application code should prefer any of:
|
||||||
|
* 1. recover_native2(src_td, src_address)
|
||||||
|
* 2. Reflect::recover_native<T>(src_td, src_address)
|
||||||
|
* 3. TaggedPtr(src_td,src_address).recover_native<T>()
|
||||||
|
* instead of src_td->recover_native<T>()
|
||||||
|
*
|
||||||
|
* (note: awkwardness here is that we don't have access to {Reflect.hpp, TaggedPtr.hpp}
|
||||||
|
* from this .hpp file, since TypeDescr.hpp is included by those headers)
|
||||||
|
**/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
[[deprecated]]
|
||||||
T * recover_native(void * address) const {
|
T * recover_native(void * address) const {
|
||||||
if (this->is_native<T>()) {
|
if (this->is_native<T>()) {
|
||||||
return reinterpret_cast<T *>(address);
|
return reinterpret_cast<T *>(address);
|
||||||
|
|
@ -179,6 +217,22 @@ namespace xo {
|
||||||
}
|
}
|
||||||
} /*recover_native*/
|
} /*recover_native*/
|
||||||
|
|
||||||
|
/** safe downcast -- like dynamic_cast<>, but does not require a source type.
|
||||||
|
*
|
||||||
|
* Application code should prefer TaggedPtr::recover_native<T>()
|
||||||
|
*
|
||||||
|
* TODO: need variation on this to correctly-handle function types,
|
||||||
|
* since for exampple cast from void* -> void (*)() is not allowed
|
||||||
|
**/
|
||||||
|
template<typename T>
|
||||||
|
T * recover_native2(TypeDescr address_td, void * address) const {
|
||||||
|
if (this == address_td) {
|
||||||
|
return reinterpret_cast<T *>(address);
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} /*recover_native2*/
|
||||||
|
|
||||||
bool is_pointer() const { return this->tdextra_->is_pointer(); }
|
bool is_pointer() const { return this->tdextra_->is_pointer(); }
|
||||||
bool is_vector() const { return this->tdextra_->is_vector(); }
|
bool is_vector() const { return this->tdextra_->is_vector(); }
|
||||||
bool is_struct() const { return this->tdextra_->is_struct(); }
|
bool is_struct() const { return this->tdextra_->is_struct(); }
|
||||||
|
|
@ -255,7 +309,9 @@ namespace xo {
|
||||||
* - s_type_table_map[TypeInfoRef(x->typeinfo())] = x
|
* - s_type_table_map[TypeInfoRef(x->typeinfo())] = x
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* hashmap of all TypeDescr instances, indexed by . singleton */
|
/* hashmap of all native TypeDescr instances, indexed by typeinfo.
|
||||||
|
* singleton.
|
||||||
|
*/
|
||||||
static std::unordered_map<TypeInfoRef, std::unique_ptr<TypeDescrBase>> s_type_table_map;
|
static std::unordered_map<TypeInfoRef, std::unique_ptr<TypeDescrBase>> s_type_table_map;
|
||||||
/* hashmap of (presumed) duplicate TypeInfoRef values.
|
/* hashmap of (presumed) duplicate TypeInfoRef values.
|
||||||
* This happens with clang sometimes when the same type is referenced
|
* This happens with clang sometimes when the same type is referenced
|
||||||
|
|
@ -269,8 +325,13 @@ namespace xo {
|
||||||
private:
|
private:
|
||||||
/* unique id# for this type */
|
/* unique id# for this type */
|
||||||
TypeId id_;
|
TypeId id_;
|
||||||
/* typeinfo for type T */
|
/** typeinfo for type T, if available. nullptr otherwise.
|
||||||
std::type_info const * typeinfo_ = nullptr;
|
*
|
||||||
|
* 1. Always available for type-descriptions constructed via Reflect::require<T>.
|
||||||
|
* 2. Always missing for manually-constructed TypeDescr instances, for example
|
||||||
|
* see Lambda.cpp in xo-expression.
|
||||||
|
**/
|
||||||
|
std::type_info const * native_typeinfo_ = nullptr;
|
||||||
/* canonical name for this type (see demangle.hpp for type_name<T>())
|
/* canonical name for this type (see demangle.hpp for type_name<T>())
|
||||||
* e.g.
|
* e.g.
|
||||||
* xo::option::Px2
|
* xo::option::Px2
|
||||||
|
|
|
||||||
|
|
@ -124,11 +124,11 @@ namespace xo {
|
||||||
} /*namespace*/
|
} /*namespace*/
|
||||||
|
|
||||||
TypeDescrBase::TypeDescrBase(TypeId id,
|
TypeDescrBase::TypeDescrBase(TypeId id,
|
||||||
std::type_info const * tinfo,
|
std::type_info const * native_tinfo,
|
||||||
std::string_view canonical_name,
|
std::string_view canonical_name,
|
||||||
std::unique_ptr<TypeDescrExtra> tdextra)
|
std::unique_ptr<TypeDescrExtra> tdextra)
|
||||||
: id_{std::move(id)},
|
: id_{std::move(id)},
|
||||||
typeinfo_{tinfo},
|
native_typeinfo_{native_tinfo},
|
||||||
canonical_name_{std::move(canonical_name)},
|
canonical_name_{std::move(canonical_name)},
|
||||||
short_name_{unqualified_name(canonical_name_)},
|
short_name_{unqualified_name(canonical_name_)},
|
||||||
tdextra_{std::move(tdextra)}
|
tdextra_{std::move(tdextra)}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue