Boost logo

Boost :

Subject: Re: [boost] [rpc] Introducing Boost.Reflect, Boost.CMT, and Boost.RPC
From: Julien Nitard (julien.nitard_at_[hidden])
Date: 2011-08-04 21:23:06


Hi Daniel,

> > - Annoying warning in reflect.hpp line 84 (multi-line comment), triggered
> [...]
> I removed the line.

Thanks for the quick reaction.

> > - Remove the const in operator()

[...]
> A mutable reference makes no sense:

Indeed it doesn't. Thanks for pointing it out.

I have another use case :

After having written the byte swapper and csv output, the next logical
application for reflection is a parser.
The input is something of the form:
{ { message_type = name } | key1=value1 | key2={ ... } | key3=value3 |
... }

I am writing a parser that explode this in structs assuming that the "name"
is the name of a struct and the keys are its members. IE. I can create a
struct like this:

struct name
{
    type key1;
    type key2;
    ...
}

and it will be automatically parsed (and it works with sub structures).

The parsing need to create a map of (names, parser) functions so that when
it reads a key it can call the appropriate parser function and set the
property.

I came up with the following pattern to solve the problem: I have a
Parseable template base class (CRTP) that provides a static GetMembers()
function that return (and create) the said map.

    template <class concrete>
    class Parseable
    {
    public:
        typedef function<const char*(concrete&, const char*)> Parser;
        typedef map<string, Parser> ParserMap;

        /// <summary>The list of members in the concrete class.</summary>
        static ParserMap& GetMembers()
        {
            static ParserMap _members = InitMembers();
            return _members;
        }

    private:
        // Private members used for initialization.
        static ParserMap InitMembers()
        {
            using namespace boost::reflect;
            ParserMap result;
            reflector<concrete>::visit( ParserInitVisitor(result) );
            return result;
        }

        /// <summary> Used to init the 'Members' collection of parseable
types. </summary>
        struct ParserInitVisitor
        {
            ParserInitVisitor(ParserMap& members)
                : _members(members)
            { }

            template <class Class, class Member>
            void operator()(Member Class::*m, const char* name) const
            {
                _members[string(name)] = Setter<Class, Member>(m);
            }

        private:
            ParserMap& _members;
        };
    };

The Setter function object takes a parseable object and calls the
appropriate parser and on object.*m and the input string and returns the
string left to parse.

All this to say that boost::reflect seems to have a lot of patterns ... and
I think there's work to be done in the library to factor some boilerplate
code, but I am not sure how it can be done (if at all). I think at least you
could document the ones you think will be used more often. I also think that
the calculator example though impressive, is a bit obscure for a newcomer to
your library.

The next thing that I'll be working on is that I need to map the names of
the struct to their string counterpart as the first type of the parsing
process, and here again it has to be done manually. That is I'll have to
find a way to list my types in a map <string,type> while I am already
calling BOOST_REFLECT that could do it at the same time (or at least I think
it can, I didn't try yet). I think it is one pattern that would be a very
useful addition.

Would you be interested if I worked on patch to do this ?

Regards,

Julien


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk