David Abrahams wrote:

> Alexander Nasonov <[EMAIL PROTECTED]> 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


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to