我想在 C++ 中有一个结构(或类似的东西),它允许动态访问它的成员。它应该有一个通用的 getter 和 setter,它们接收成员名称作为字符串,并返回某种变体类型(例如boost::variant
)。
我认为它可以boost::fusion::map
通过添加一个表示每个成员名称的字符串,并在字符串和 getter 或 setter 函数之间构建一个 STL 映射来实现。我不想重新发明轮子,所以我希望类似的东西已经存在。
你怎么看?我的想法可行吗?你知道实现我目标的其他方法吗?
我想在 C++ 中有一个结构(或类似的东西),它允许动态访问它的成员。它应该有一个通用的 getter 和 setter,它们接收成员名称作为字符串,并返回某种变体类型(例如boost::variant
)。
我认为它可以boost::fusion::map
通过添加一个表示每个成员名称的字符串,并在字符串和 getter 或 setter 函数之间构建一个 STL 映射来实现。我不想重新发明轮子,所以我希望类似的东西已经存在。
你怎么看?我的想法可行吗?你知道实现我目标的其他方法吗?
fusion 是一种方法,但为什么不将您的“字段”存储在 astd::map
键控中std::string
,其中有效负载是boost::variant
...
IE
struct generic
{
std::map<std::string, boost::variant<foo, bar, bob, int, double> > _impl;
};
然后你可以在你的getter/setter中查找密钥......
哎呀,把它包起来variant
,optional
你可以有可选的字段!
一个更复杂的例子:
class foo
{
public:
typedef boost::variant<int, double, float, string> f_t;
typedef boost::optional<f_t&> return_value;
typedef map<string, return_value> ref_map_t;
foo() : f1(int()), f2(double()), f3(float()), f4(string()), f5(int())
{
// save the references..
_refs["f1"] = return_value(f1);
_refs["f2"] = return_value(f2);
_refs["f3"] = return_value(f3);
_refs["f4"] = return_value(f4);
_refs["f5"] = return_value(f5);
}
int getf1() const { return boost::get<int>(f1); }
double getf2() const { return boost::get<double>(f2); }
float getf3() const { return boost::get<float>(f3); }
string const& getf4() const { return boost::get<string>(f4); }
int getf5() const { return boost::get<int>(f5); }
// and setters..
void setf1(int v) { f1 = v; }
void setf2(double v) { f2 = v; }
void setf3(float v) { f3 = v; }
void setf4(std::string const& v) { f4 = v; }
void setf5(int v) { f5 = v; }
// key based
return_value get(string const& key)
{
ref_map_t::iterator it = _refs.find(key);
if (it != _refs.end())
return it->second;
return return_value();
}
template <typename VT>
void set(string const& key, VT const& v)
{
ref_map_t::iterator it = _refs.find(key);
if (it != _refs.end())
*(it->second) = v;
}
private:
f_t f1;
f_t f2;
f_t f3;
f_t f4;
f_t f5;
ref_map_t _refs;
};
int main(void)
{
foo fancy;
fancy.setf1(1);
cout << "f1: " << fancy.getf1() << endl;
fancy.set("f1", 10);
cout << "f1: " << fancy.getf1() << endl;
return 0;
}
我为此做的是一个类似于 boost::cons 的类型列表,其中包含我的成员和某种描述。然后,我通过“链式”函数调用将我的成员连续添加到“元信息”数据结构中来构建此映射。整个事情看起来非常类似于在 boost.python 中定义一个类。如果你真的使用 boost::cons,它也应该在 boost.fusion 中作为一个序列工作,这样你就可以很好地迭代你的数据。也许您可以使用 boost.fusion 映射来在运行时获取 log(n) 访问时间,但在可变参数模板可用之前,它们的大小似乎是有限的。
您要求 C++ 中的反射,我认为这是不可用的。你必须想出你自己的东西。