> > Oh... I thought about variable names too! Did I understood correctly
> > that you use scheme with const and non-const 'describe'?
>
> Here is what I do currently:
>
> struct X
> {
>     explicit X(int i = 0): i(i)
>     {
>     }
>
>     virtual ~X()
>     {
>     }
>
>     int i;
> };
>
> template<class R> void read(R & r, X & x)
> {
>     begin_struct(r);
>     read(r, x.i);
>     end_struct(r);
> }
>
> template<class W> void write(W & w, X const & x)
> {
>     begin_struct(w);
>     write(w, x.i);
>     end_struct(w);
> }
>
> template<class W, class A> void write(W & w, X const & x, A const & a)
> {
>     begin_struct(w, a);
>     write(w, x.i, "i");
>     end_struct(w, a);
> }
>
> This is quite repetitive and error-prone, but without
reflection/metadata...

Actually I use a similar aproach to describe/serialize objects. This is a
minimalist example showing my approach..

#include <iostream>
#include <typeinfo.h>
#include <sstream>

template<typename DATA>
struct Description
{};

struct Person
{
    Person() {}
    Person(const std::string& firstName, const std::string& lastName, int
birthYear) : m_firstName(firstName), m_lastName(lastName),
m_birthYear(birthYear) {}
    std::string m_firstName;
    std::string m_lastName;
    int m_birthYear;
};

template<>
struct Description<Person>
{
    template<typename   STRUCT, typename VISITOR>
        static void Describe(STRUCT& data, VISITOR& visitor)
    {
        visitor.Begin(data);
        visitor.Attribute(data.m_firstName, "FirstName");
        visitor.Attribute(data.m_lastName, "LastName");
        visitor.Attribute(data.m_birthYear, "BirthYear");
        visitor.End(data);
    }
};

template<>
struct Description<const Person> : public Description<Person> {} //
Specialization for deficient compiler

template<typename STRUCT, typename VISITOR>
void Describe(STRUCT& data, VISITOR& visitor)
{
    Description<STRUCT>::Describe(data, visitor);
    // For non deficient compilers
    //Description< boost::remove_const<STRUC>::type>::Describe(data,
visitor);
};

class Writer
{
    std::ostream* m_stream;
public:
    Writer(std::ostream& stream) : m_stream(&stream) {}
    template<typename STRUCT>
        void Begin(const STRUCT& data)
    {
        *m_stream << "Begin:" << typeid(data).name() << std::endl;
    }

    template<typename STRUCT>
        void End(const STRUCT& data)
    {
        *m_stream << "End:" << typeid(data).name() << std::endl;
    }

    template<typename ATTRIBUTE>
        void Attribute(const ATTRIBUTE& attribute, const std::string& name)
    {
        *m_stream << name.c_str() << "{" <<  typeid(attribute).name() << "}=
" << attribute << std::endl;
    }

    template<>
        void Attribute(const std::string& attribute, const std::string&
name)
    {
        *m_stream << name.c_str() << "= " << attribute.c_str() << std::endl;
    }

};


class Reader
{
    std::istream* m_stream;
public:
    Reader(std::istream& stream) : m_stream(&stream) {}
    template<typename STRUCT>
        void Begin(STRUCT& data, const std::string& name)
    {
        std::string s;
        std::getline(*m_stream,s);
    }

    template<typename STRUCT>
        void End(STRUCT& data, const std::string& name)
    {
        std::string s;
        std::getline(*m_stream,s);
    }

    template<typename ATTRIBUTE>
        void Attribute(ATTRIBUTE& attribute, const std::string& name)
    {
        std::string s;
        *m_stream >> s >> attribute;
    }
};

int main(int argc, char* argv[])
{
    Person p("Michel", "Andre", 1971);
    std::stringstream ss;
    Writer w(ss);
    Describe(p, w);
    Person p1;
    Reader r(ss);
    Describe(p1, r);
    Writer w1(std::cout);
    Describe(p1, w1);
    return 0;
}

I beleive this is const safe since STRUCT& can be bound to const Person& if
a const safe version is needed.

It also solves the problem with needing two or 3 separate description/stream
functions. The version we use is a bit more sophisticated but this is the
base (Basically the Description class is used as a streaming policy traits
class containing more information about a type and also carrying information
if a class has a specialized description and an unique string and numeric id
for the type). All error detection is omitted. I have 4 formats today a xml,
binary, text, db.

Maybe this approach could be modified and used to build a serialization
library on? At least I've used it successfully in several projects, but
maybe the a aproach is to simplistic for a complex streaming library.

Regards
/Michel
PS. I've probably should give a tons of credits for this but I have refined
an idea from a colleague who read an article in CUJ or C++ Report I haven't
been able to find it, maybe someone of you can helo me so I can give due
credits for the solution DS.