これを行うには複雑な方法がありますが、最初にやろうとしていたことを正確に実行します (任意の構造に簡単に適用できます)。
#include <iostream>
#include <string>
#include <map>
/////////////////////////////////////////
// HELPERS
template<class T>
class MemberPtrBase
{
public:
virtual std::istream& Read(std::istream& is, T& object) = 0;
virtual ~MemberPtrBase() {}
};
template<class T, class V>
class MemberPtr : public MemberPtrBase<T>
{
V T::*member;
public:
MemberPtr(V T::*ptr)
: member(ptr)
{}
std::istream& Read(std::istream& is, T& object)
{
return is >> (object.*member);
}
};
template<class T>
class MemberMap
{
typedef std::map<std::string, MemberPtrBase<T>*> MapType;
MapType members;
public:
MemberMap() {}
~MemberMap()
{
for (MapType::iterator it = members.begin(); it != members.end(); ++it)
delete it->second;
}
template<class V>
void Register(std::string const& name, V T::*ptr)
{
members[name] = new MemberPtr<T, V>(ptr);
}
std::istream& ReadValue(std::istream& is, T& object)
{
std::string name;
is >> name;
if (members.find(name) == members.end())
{
std::cerr << "Unknown member: " << name << std::endl;
return is;
}
return members[name]->Read(is, object);
}
};
///////////////////////////////////////////
class Box
{
public:
int width;
int height;
int length;
static MemberMap<Box> members;
};
MemberMap<Box> Box::members;
class Circle
{
public:
int x;
int y;
int radius;
static MemberMap<Circle> members;
};
MemberMap<Circle> Circle::members;
int main()
{
Box::members.Register("width", &Box::width);
Box::members.Register("height", &Box::height);
Box::members.Register("length", &Box::length);
Circle::members.Register("x", &Circle::x);
Circle::members.Register("y", &Circle::y);
Circle::members.Register("radius", &Circle::radius);
Box box;
Box::members.ReadValue(std::cin, box);
return 0;
}