> > 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.