ma740988 said:
Not that much anymore. Has been pretty much solved in the boost library.
Could you show a synopsis on how you're doing this?
The following is some scratch I put together for a presentation at a
local college. It's functional and almost complete. It doesn't address
problems you'll have with namespaces and using the MSVC method in g++ or
others.
#include <iostream>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/begin.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/for_each.hpp>
//#define MSVC // uncomment if you have visual studio. Also fine in g++
#define DECLARE_FIELD(NAME,TYPE) \
struct NAME \
{ \
typedef TYPE type; \
static char const* name() { return #NAME ; } \
}
template < typename CONT, typename FIELD, typename TYPE, TYPE CONT::*addr >
struct record_field_desc
{
typedef CONT member_of;
typedef FIELD field;
typedef TYPE type;
static TYPE get(CONT const& cont) { return cont.*addr; }
static void set(CONT & cont, TYPE const& value) { cont.*addr = value; }
};
template < typename REC >
struct meta
{
typedef typename REC::meta type;
};
#ifndef MSVC
#define BEGIN_META(CONT) \
struct meta { typedef boost::mpl::vector<CONT
#define ADD_FIELD(CONT, FIELD, ADDR) \
, record_field_desc<CONT, FIELD, FIELD::type, ADDR>
#define END_META() \
typedef boost::mpl::next<boost::mpl::begin<fields>::type>::type begin; \
typedef boost::mpl::end<fields>::type end; \
};
#else
#define BEGIN_META(CONT) \
struct CONT_meta \
{ \
typedef boost::mpl::vector<CONT
#define ADD_FIELD(CONT, FIELD, ADDR) \
, record_field_desc<CONT, FIELD, FIELD::type, ADDR>
#define END_META(CONT) \
typedef boost::mpl::next< boost::mpl::begin<fields>::type >::type begin; \
typedef boost::mpl::end<fields>::type end; \
}; \
\
template <> struct meta<CONT> { typedef CONT_meta type; };
#endif
DECLARE_FIELD(test1, int);
DECLARE_FIELD(test2, double);
DECLARE_FIELD(test3, long);
struct test_record
{
int x;
double y;
#ifndef MSVC
BEGIN_META(test_record)
ADD_FIELD(test_record, test1, &test_record::x)
ADD_FIELD(test_record, test2, &test_record::y)
//ADD_FIELD(test_record, test3, &test_record::y) // uncomment to
see error
END_META()
#endif
};
#ifdef MSVC
BEGIN_META(test_record)
ADD_FIELD(test_record, test1, &test_record::x)
ADD_FIELD(test_record, test2, &test_record::y)
END_META(test_record)
#endif
// UTILITY STUFF
template < typename T >
struct type_desc
{
static char const* desc() { return typeid(T).name(); }
};
template <>
struct type_desc<int> { static char const* desc() { return "integer"; } };
template <>
struct type_desc<double> { static char const* desc() { return "real
number"; } };
template < typename REC >
struct record_reader
{
struct field_reader
{
REC & rec;
field_reader(REC & r) : rec(r) {}
template < typename FIELD_DESC >
void operator() (FIELD_DESC const&) const
{
typedef typename FIELD_DESC::type type;
std::cout << "Enter a " << type_desc<type>::desc() << " for " <<
FIELD_DESC::field::name() << ": ";
type t;
std::cin >> t;
FIELD_DESC::set(rec, t);
}
};
static REC read_record()
{
REC rec;
boost::mpl::for_each< typename meta<REC>::type >(field_reader(rec));
return rec;
}
};
template < typename REC >
struct record_writer
{
struct field_writer
{
REC const& rec;
field_writer(REC const& r) : rec(r) {}
template < typename FIELD_DESC >
void operator() (FIELD_DESC const&) const
{
std::cout << "Value for "
<< FIELD_DESC::field::name()
<< " is: " << FIELD_DESC::get(rec) << std::endl;
}
};
static void write_record(REC const& r)
{
boost::mpl::for_each< typename meta<REC>::type >(field_writer(r));
}
};
int main()
{
test_record rec = {};
record_writer<test_record>::write_record(rec);
rec = record_reader<test_record>::read_record();
record_writer<test_record>::write_record(rec);
}