内省仿真 ? 这听起来像是一个挑战,这是肯定的。
该界面并不真正让我满意,所以我会提出一个替代方案:
struct MyType
{
int fieldA;
int fieldB;
void setField(std::string const& field, std::string const& value);
};
现在的挑战是setField
选择正确的领域,而且确实一张地图似乎很合适。但是我们需要在某处封装类型信息(除非您打算只使用整数,在这种情况下......没有困难),所以函子映射是有序的。
static std::map<std::string, Functor<MyType>*> M_Map;
// where Functor is
template <class Type>
struct Functor
{
virtual void set(Type& t, std::string const& value) const = 0;
};
// And a specialization would be
struct SetfieldA : public Functor<MyType>
{
virtual void set(MyType& t, std::string const& value) const
{
std::istringstream stream(value);
stream >> t.fieldA;
// some error handling could be welcome there :)
}
};
注意使用std::istringstream
,现在您可以支持任何类型,只要它们正确地与 . 交互即可std::istream
。因此,您可以支持用户定义的类。
当然,这里的部分都是关于自动化的!
和像宏一样的自动化。
#define INTROSPECTED(MyType_) \
private: \
typedef Functor<MyType_> intro_functor; \
typedef std::map<std::string, intro_functor const*> intro_map; \
static intro_map& IntroMap() { static intro_map M_; return M_; } \
public: \
static void IntroRegister(std::string const& field, intro_functor const* f){ \
IntroMap()[field] = f; } \
void setField(std::string const& field, std::string const& value) { \
intro_map::const_iterator it = IntroMap().find(field); \
if (it != IntroMap().end()) it->second->set(*this, value); }
#define INTROSPECT_FIELD(Class_, Name_) \
struct Set##Name_: public Functor<Class_> { \
virtual void set(Class_& t, std::string const& value) { \
std::istringstream stream(value); stream >> t.Name_; } } Setter##Name_; \
Class_::IntroRegister(#Name_, Setter##Name_)
像这样的用法:
// myType.h
struct MyType
{
INTROSPECTED(MyType);
int fieldA;
int fieldB;
};
// myType.cpp
INTROSPECT_FIELD(MyType, fieldA);
INTROSPECT_FIELD(MyType, fieldB);
// Any file
MyType t;
t.set("fieldA", "3");
当然,通常的警告适用:在我的脑海中,从未编译过它,可能会杀死小猫甚至更糟。