reflect: insert xo/ subdir into include path
This commit is contained in:
parent
ba95d0a40c
commit
6be9037f10
20 changed files with 179 additions and 184 deletions
235
include/xo/reflect/struct/StructMember.hpp
Normal file
235
include/xo/reflect/struct/StructMember.hpp
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
/* @file StructMember.hpp */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xo/reflect/TypeDescr.hpp"
|
||||
#include "xo/reflect/EstablishTypeDescr.hpp"
|
||||
#include "xo/reflect/TaggedPtr.hpp"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace xo {
|
||||
namespace reflect {
|
||||
class AbstractStructMemberAccessor {
|
||||
public:
|
||||
virtual ~AbstractStructMemberAccessor() = default;
|
||||
|
||||
/* get tagged pointer referring to this member of the object at *struct_addr */
|
||||
TaggedPtr member_tp(void * struct_addr) const;
|
||||
|
||||
/* get type-description object for struct
|
||||
* containing this member. useful for consistency checking.
|
||||
*/
|
||||
virtual TypeDescr struct_td() const = 0;
|
||||
|
||||
/* get type-description object for this member
|
||||
* e.g. if this member represents Foo::bar_ in
|
||||
* struct Foo { int bar_; };
|
||||
* then
|
||||
* .member_td() => Reflect::require<int>();
|
||||
*/
|
||||
virtual TypeDescr member_td() const = 0;
|
||||
|
||||
/* get address of a particular member, given parent address */
|
||||
virtual void * address(void * struct_addr) const = 0;
|
||||
|
||||
virtual std::unique_ptr<AbstractStructMemberAccessor> clone() const = 0;
|
||||
}; /*AbstractStructMemberAccessor*/
|
||||
|
||||
/* GeneralStructMemberAccessor
|
||||
*
|
||||
* Use this to handle access to possibly-inherited struct members:
|
||||
*
|
||||
* struct Foo { int x_; }
|
||||
* struct Bar { char * y_; }
|
||||
* struct Quux : public Foo, public Bar { bool z_; }
|
||||
*
|
||||
* want to be able to access Bar::y from a Quux instance.
|
||||
* in example, would use GenericStructMemberAccessor<>
|
||||
* with:
|
||||
* StructT = Quux,
|
||||
* OwnerT = Bar,
|
||||
* MemberT = char*
|
||||
*
|
||||
* Require:
|
||||
* StructT* is assignable to OwnerT* (because StructT --isa--> OwnerT)
|
||||
*/
|
||||
template <typename StructT, typename OwnerT, typename MemberT>
|
||||
class GeneralStructMemberAccessor : public AbstractStructMemberAccessor {
|
||||
public:
|
||||
/* pointer to a OwnerT member of type MemberT */
|
||||
using Memptr = MemberT OwnerT::*;
|
||||
|
||||
public:
|
||||
GeneralStructMemberAccessor(Memptr memptr) : member_td_{EstablishTypeDescr::establish<MemberT>()},
|
||||
memptr_{memptr} {}
|
||||
GeneralStructMemberAccessor(GeneralStructMemberAccessor const & x) = default;
|
||||
virtual ~GeneralStructMemberAccessor() = default;
|
||||
|
||||
static std::unique_ptr<GeneralStructMemberAccessor> make(Memptr memptr) {
|
||||
return std::unique_ptr<GeneralStructMemberAccessor>(new GeneralStructMemberAccessor(memptr)); }
|
||||
|
||||
/* get member address given address of parent struct
|
||||
* (i.e. from Struct*, not from OwnerT*)
|
||||
*/
|
||||
MemberT * address_impl(StructT * self_addr) const {
|
||||
OwnerT * owner_addr = self_addr;
|
||||
|
||||
return &(owner_addr->*memptr_);
|
||||
} /*address_impl*/
|
||||
|
||||
// ----- Inherited from AbstractStructMemberAccessor -----
|
||||
|
||||
#ifdef OBSOLETE
|
||||
virtual TaggedPtr member_tp(void * struct_addr) const override {
|
||||
/* FIXME: this reports declared type of member, instead of
|
||||
* (possibly narrower) actual type of member
|
||||
*/
|
||||
|
||||
return this->member_td_->most_derived_self_tp(this->address(struct_addr));
|
||||
//return TaggedPtr(this->member_td_, this->address(struct_addr));
|
||||
} /*member_tp*/
|
||||
#endif
|
||||
|
||||
virtual TypeDescr struct_td() const override { return EstablishTypeDescr::establish<StructT>(); }
|
||||
|
||||
virtual TypeDescr member_td() const override { return this->member_td_; }
|
||||
|
||||
virtual void * address(void * struct_addr) const override {
|
||||
return this->address_impl(reinterpret_cast<StructT *>(struct_addr));
|
||||
} /*address*/
|
||||
|
||||
virtual std::unique_ptr<AbstractStructMemberAccessor> clone() const override {
|
||||
return std::unique_ptr<AbstractStructMemberAccessor>
|
||||
(new GeneralStructMemberAccessor(*this));
|
||||
} /*clone*/
|
||||
|
||||
private:
|
||||
/* type description for MemberT; .memptr is pointer-to-member-of-OwnerT,
|
||||
* where that member has type MemberT
|
||||
*/
|
||||
TypeDescr member_td_ = nullptr;
|
||||
/* pointer to member of OwnerT */
|
||||
Memptr memptr_ = nullptr;
|
||||
}; /*GeneralStructMemberAccessor*/
|
||||
|
||||
/* struct-member accessor via delegation,
|
||||
* to accessor of a parent (or some other ancestor) class.
|
||||
*
|
||||
* struct Foo { int x_; }
|
||||
* struct Bar { char * y_; }
|
||||
*
|
||||
* auto bar_x_access = GeneralStructMemberAccessor<Bar, Foo, int>::make(&Foo::x_);
|
||||
*
|
||||
* or equivalently:
|
||||
* auto foo_x_access = GeneralStructMemberAccessor<Foo, Foo, int>::make(&Foo::x_);
|
||||
* auto bar_x_access = AncestorStructMemberAccessor<Bar, Foo>::adopt(foo_x_access);
|
||||
*
|
||||
* can use the 2nd form to adopt accessors from an already-reflected ancestor class
|
||||
*
|
||||
* Require:
|
||||
* - StructT -isa-> AncestorT
|
||||
*/
|
||||
template <typename StructT, typename AncestorT>
|
||||
class AncestorStructMemberAccessor : public AbstractStructMemberAccessor {
|
||||
public:
|
||||
AncestorStructMemberAccessor(std::unique_ptr<AbstractStructMemberAccessor> ancestor_accessor)
|
||||
: ancestor_accessor_{std::move(ancestor_accessor)} {}
|
||||
AncestorStructMemberAccessor(AncestorStructMemberAccessor const & x) = default;
|
||||
virtual ~AncestorStructMemberAccessor() = default;
|
||||
|
||||
static std::unique_ptr<AncestorStructMemberAccessor>
|
||||
adopt(std::unique_ptr<AbstractStructMemberAccessor> ancestor_accessor) {
|
||||
return std::unique_ptr<AncestorStructMemberAccessor>
|
||||
(new AncestorStructMemberAccessor(std::move(ancestor_accessor)));
|
||||
} /*adopt*/
|
||||
|
||||
void * address_impl(StructT * self_addr) const {
|
||||
/* to use access-via-ancestor, need to convert to ancestor pointer */
|
||||
AncestorT * ancestor_addr = self_addr;
|
||||
|
||||
return this->ancestor_accessor_->address(ancestor_addr);
|
||||
} /*address_impl*/
|
||||
|
||||
// ----- inherited from AbstractStructMemberAccessor -----
|
||||
|
||||
#ifdef OBSOLETE
|
||||
virtual TaggedPtr member_tp(void * struct_addr) const override {
|
||||
AncestorT * ancestor_addr = reinterpret_cast<StructT *>(struct_addr);
|
||||
|
||||
return this->ancestor_accessor_->member_tp(ancestor_addr);
|
||||
} /*member_tp*/
|
||||
#endif
|
||||
|
||||
virtual TypeDescr struct_td() const override { return EstablishTypeDescr::establish<StructT>(); }
|
||||
virtual TypeDescr member_td() const override { return this->ancestor_accessor_->member_td(); }
|
||||
|
||||
virtual void * address(void * struct_addr) const override {
|
||||
return this->address_impl(reinterpret_cast<StructT *>(struct_addr));
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<AbstractStructMemberAccessor> clone() const override {
|
||||
return std::unique_ptr<AbstractStructMemberAccessor>
|
||||
(new AncestorStructMemberAccessor(std::move(this->ancestor_accessor_->clone())));
|
||||
} /*clone*/
|
||||
|
||||
private:
|
||||
/* .ancestor_accessor fetches some particular member of AncestorT */
|
||||
std::unique_ptr<AbstractStructMemberAccessor> ancestor_accessor_;
|
||||
}; /*AncestorStructMemberAccessor*/
|
||||
|
||||
/* describes a member of a struct/class
|
||||
* see [reflect/StructReflector.hpp]
|
||||
*/
|
||||
class StructMember {
|
||||
public:
|
||||
StructMember() = default;
|
||||
StructMember(std::string const & name,
|
||||
std::unique_ptr<AbstractStructMemberAccessor> accessor)
|
||||
: member_name_{name}, accessor_{std::move(accessor)} {}
|
||||
StructMember(StructMember && x)
|
||||
: member_name_{std::move(x.member_name_)},
|
||||
accessor_{std::move(x.accessor_)} {}
|
||||
|
||||
static StructMember null();
|
||||
|
||||
std::string const & member_name() const { return member_name_; }
|
||||
|
||||
TaggedPtr get_member_tp(void * struct_addr) const { return this->accessor_->member_tp(struct_addr); }
|
||||
TypeDescr get_struct_td() const { return this->accessor_->struct_td(); }
|
||||
TypeDescr get_member_td() const { return this->accessor_->member_td(); }
|
||||
//void * get_member_addr(void * struct_addr) const { return this->accessor_->address(struct_addr); }
|
||||
|
||||
/* make copy that accesses this member, but starting
|
||||
* from pointer to some derived class DescendantT,
|
||||
* instead of from container type StructT known to (but not exposed by) *this
|
||||
*/
|
||||
template <typename DescendantT, typename StructT>
|
||||
StructMember for_descendant() const {
|
||||
assert(EstablishTypeDescr::establish<StructT>() == this->get_struct_td());
|
||||
|
||||
return StructMember(this->member_name(),
|
||||
std::move(AncestorStructMemberAccessor<DescendantT, StructT>::adopt
|
||||
(std::move(this->accessor_->clone()))));
|
||||
} /*for_descendant*/
|
||||
|
||||
StructMember & operator=(StructMember && x) {
|
||||
member_name_ = std::move(x.member_name_);
|
||||
accessor_ = std::move(x.accessor_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
/* member name, e.g. foo if
|
||||
* struct StructT { MemberT foo; }
|
||||
*/
|
||||
std::string member_name_;
|
||||
/* T recd;
|
||||
* this->accessor_->address_impl(&recd) ==> &(recd.member)
|
||||
*/
|
||||
std::unique_ptr<AbstractStructMemberAccessor> accessor_;
|
||||
}; /*StructMember*/
|
||||
} /*namespace reflect*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end StructMember.hpp */
|
||||
95
include/xo/reflect/struct/StructTdx.hpp
Normal file
95
include/xo/reflect/struct/StructTdx.hpp
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/* @file StructTdx.hpp */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xo/reflect/TypeDescrExtra.hpp"
|
||||
#include "xo/reflect/TaggedPtr.hpp"
|
||||
#include "StructMember.hpp"
|
||||
//#include "xo/reflect/struct/StructMember.hpp"
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace xo {
|
||||
namespace reflect {
|
||||
/* Extra type-associated information for a struct/class.
|
||||
* We use this to preserve information about memory layout
|
||||
* at runtime
|
||||
*/
|
||||
class StructTdx : public TypeDescrExtra {
|
||||
public:
|
||||
/* named ctor idiom. create new instance for struct with given member list
|
||||
*
|
||||
* to_self_tp. use this function to support .most_derived_self_tp()
|
||||
*/
|
||||
static std::unique_ptr<StructTdx> make(std::vector<StructMember> member_v,
|
||||
bool have_to_self_tp,
|
||||
std::function<TaggedPtr (void *)> to_self_tp);
|
||||
|
||||
/* specialization for std::pair<Lhs, Rhs>
|
||||
* coordinates with [reflect/Reflect.hpp]
|
||||
*/
|
||||
template<typename Lhs, typename Rhs>
|
||||
static std::unique_ptr<StructTdx> pair() {
|
||||
using struct_t = std::pair<Lhs, Rhs>;
|
||||
|
||||
std::vector<StructMember> mv;
|
||||
{
|
||||
auto lhs_access
|
||||
(GeneralStructMemberAccessor<struct_t, struct_t, Lhs>::make
|
||||
(&struct_t::first));
|
||||
|
||||
mv.push_back(StructMember("first", std::move(lhs_access)));
|
||||
}
|
||||
{
|
||||
auto rhs_access
|
||||
(GeneralStructMemberAccessor<struct_t, struct_t, Rhs>::make
|
||||
(&struct_t::second));
|
||||
|
||||
mv.push_back(StructMember("second", std::move(rhs_access)));
|
||||
}
|
||||
|
||||
std::function<TaggedPtr (void *)> null_to_self_tp;
|
||||
|
||||
return make(std::move(mv),
|
||||
false /*!have_to_self_tp*/,
|
||||
null_to_self_tp);
|
||||
} /*pair*/
|
||||
|
||||
// ----- Inherited from TypeDescrExtra -----
|
||||
|
||||
virtual Metatype metatype() const override { return Metatype::mt_struct; }
|
||||
virtual TaggedPtr most_derived_self_tp(TypeDescrBase const * object_td,
|
||||
void * object) const override {
|
||||
if (this->have_to_self_tp_) {
|
||||
return this->to_self_tp_(object);
|
||||
} else {
|
||||
return TypeDescrExtra::most_derived_self_tp(object_td, object);
|
||||
}
|
||||
}
|
||||
virtual uint32_t n_child(void * /*object*/) const override { return this->member_v_.size(); }
|
||||
virtual TaggedPtr child_tp(uint32_t i, void * object) const override;
|
||||
virtual std::string const & struct_member_name(uint32_t i) const override;
|
||||
virtual StructMember const * struct_member(uint32_t i) const override;
|
||||
|
||||
private:
|
||||
StructTdx(std::vector<StructMember> member_v,
|
||||
bool have_to_self_tp,
|
||||
std::function<TaggedPtr (void*)> to_self_tp)
|
||||
: member_v_{std::move(member_v)},
|
||||
have_to_self_tp_{have_to_self_tp},
|
||||
to_self_tp_{std::move(to_self_tp)} {}
|
||||
|
||||
private:
|
||||
/* per-instance-variable reflection details */
|
||||
std::vector<StructMember> member_v_;
|
||||
/* true if .to_self_tp() is defined */
|
||||
bool have_to_self_tp_ = false;
|
||||
/* get TaggedPtr for most-derived subtype of supplied T-instance */
|
||||
std::function<TaggedPtr (void *)> to_self_tp_;
|
||||
}; /*StructTdx*/
|
||||
|
||||
} /*namespace reflect*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end StructTdx.hpp */
|
||||
Loading…
Add table
Add a link
Reference in a new issue