|
Boost : |
From: Alexander Nasonov (alnsn-mycop_at_[hidden])
Date: 2003-07-09 06:52:54
David Abrahams wrote:
> Alexander Nasonov <alnsn-mycop_at_[hidden]> writes:
>
>> Well, sometimes it's needed at compile-time. Though, I don't know how
>> useful it is. Can you give an example?
>
> Heh, you caught me!
>
> Well, if the (member) (function) pointers are available at compile
> time they can be inlined away so that using them becomes more
> efficient.
>
> Suppose I want to write serialization code? Can you
> serialize/deserialize with a runtime-only framework?
Take a look at my example
http://groups.yahoo.com/group/boost/files/describe_classes.tar.gz
and its output (formatting added afterwards)
<object type="Driver">
<base type="Person">
<member name="gender" type="char">M</member>
<member name="birth_date" type="Date">
<member name="year" type="int">1975</member>
<member name="month" type="int">12</member>
<member name="day" type="int">8</member>
</member>
<member name="first_name" type="string">Alexander</member>
<member name="last_name" type="string">Nasonov</member>
</base>
<member name="licence_id" type="string">N/A</member>
<member name="licence_issue_date" type="Date">
<member name="year" type="int">0</member>
<member name="month" type="int">0</member>
<member name="day" type="int">0</member>
</member>
</object>
You can see that bases and compound types (like Date) are serialized
properly. There is neither pointer nor container support yet. I have some
ideas, though.
Sone words about how it works. First of all, an address of an object and a
type_info are taken. The framework always operates with void* pointer and
type_info. Several types (*_nodes) have virtual functions which casts raw
pointers back to original type and do some action. For example,
class base_node // represent a base of a concrete class
{
// ...
//
virtual void* derived_to_base(void* base_ptr) const = 0;
};
class member_node // represent a member of a concrete class
{
// ...
// Apply ->* operator to an object pointed to
// by raw_ptr and return an address of the result.
virtual void* dereference(void* raw_ptr) const = 0;
};
The framework uses these functions to access bases or members one by one
until it find elemetary types like int, char or std::string. When such type
is found you can print it or assign a new value to it.
For example, you have a raw pointer to Driver and you want to get a member
represended by some member_node node. Let's say node holds a pointer to
Driver::licence_issue_date. You can call node.dereference(raw_driver) to
get a raw address of this member and node.member_type() to get its type.
Then, if member type (Date in this case) isn't an elemenary, repeat the
procedure recursively. Otherwise, find a function that can print the
member.
>> Some other questions. How to map member pointers to names?
>
> Add a char const* const parameter? Have an additional parallel array
> of names?
>
>> How to find a member?
>
> By name? By reverse-indexing whatever structure answers the previous
> question, of course!
At compile time?! I can think of this code but I don't like it so much:
template<class Members, const char* Name>
struct find_member;
template <>
struct class_<Driver> // Taken from your post
{
typedef mpl::vector<Person> bases;
static const char licence_id[];
static const char licence_issue_date[];
static const char accelerate[];
typedef mpl::vector<
member<int Driver::*, &Driver::licence_id, licence_id>
, member<Date Driver::*, &Driver::licence_issue_date,
licence_issue_date>
, member<void (Driver::*)(), &Driver::accelerate, accelerate>
> members;
...
};
typedef find_member<
class_<Driver>::members,
class_<Driver>::licence_id
>::type result;
-- Alexander Nasonov Remove minus and all between minus and at from my e-mail for timely response
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk