访问C+中的成员+;动态和静态结构 我希望在C++中有一个结构(或类似的东西),允许动态访问成员。它应该有一个通用的getter和setter,以字符串形式接收成员名称,并返回某种类型的变量类型(例如boost::variant)
我想它可以使用访问C+中的成员+;动态和静态结构 我希望在C++中有一个结构(或类似的东西),允许动态访问成员。它应该有一个通用的getter和setter,以字符串形式接收成员名称,并返回某种类型的变量类型(例如boost::variant),c++,boost,boost-fusion,C++,Boost,Boost Fusion,我想它可以使用boost::fusion::map实现,方法是添加一个表示每个成员名称的字符串,并在字符串和getter或setter函数之间构建一个STL映射。我不想重新发明轮子,所以我希望类似的东西已经存在 你觉得怎么样?我的想法行吗?你知道实现我目标的其他方法吗 谢谢, 哈该 你要求C++,我认为它是不可用的。你必须想出自己的方法。融合是一种方法,但是为什么不将你的“字段”存储在std::map中,由std::string键入,其中有效负载是boost::variant i、 e 我为此做
boost::fusion::map
实现,方法是添加一个表示每个成员名称的字符串,并在字符串和getter或setter函数之间构建一个STL映射。我不想重新发明轮子,所以我希望类似的东西已经存在
你觉得怎么样?我的想法行吗?你知道实现我目标的其他方法吗
谢谢,
哈该 你要求C++,我认为它是不可用的。你必须想出自己的方法。融合是一种方法,但是为什么不将你的“字段”存储在
std::map
中,由std::string
键入,其中有效负载是boost::variant
i、 e
我为此做了一个类似boost::cons的类型列表,其中包含我的成员和某种描述。然后,我通过“链接”函数调用将我的成员连续添加到“meta-info”数据结构来构建这个映射。整个过程看起来非常类似于在boost.python中定义一个类。如果您实际使用boost::cons,那么它也应该在boost.fusion中作为一个序列工作,这样您就可以很好地对数据进行迭代。也许您可以使用boost.fusion映射来获取运行时的日志(n)访问时间,但在可变模板可用之前,它们的大小似乎是有限的在C++中,RTTI是可用的,你在思考……是的,C++中的反射会使它变得简单很多。我会满足于一个解决方案,它需要最少的代码行来添加一个新字段。这是可行的,但我更喜欢在编译时知道字段名的情况下进行严格的类型检查和更快的运行时访问。好的,在这种情况下,在映射中存储对真实字段的引用(类型为variant-上面的示例)…这里的问题是有5个地方需要添加新字段。这看起来像是添加了很多只包含编译时名称、字符串和类型的样板文件。也许我可以修改您的解决方案,让字段公开(以及它们的非变量类型),并在映射中存储某种包装器,将每个字段转换为变量。我最终写了一些更复杂的东西:我没有保存带有变量的映射,而是创建了一个具有字符串键的映射,以及值的getter和setter函数。然后,getter和setter访问boost::fusion::map对象以获取实际值。但这个解决方案比必要的更复杂…我想知道你为什么想要这个?即使在直接支持它的语言中,反射也是用来绕过坏代码或是为懒惰程序员编写的廉价代码的黑客。你正在打败C++提供的类型安全。到底有什么可以证明用一个简单、强大的工具来换取正确性,而用一个混乱的黑客来实现不确定性呢?@wilhelmtell:我正在努力找到正确的平衡点。我从一个非常不确定的来源读取值,它们需要以一种通用的方式进行解析和处理。只有一小部分我知道(并且想知道)正确的类型。@Dibling:我一直认为懒惰的程序员最优秀的程序员…那么关于使用各种类型的标准容器而不是结构呢?我认为boost::fusion::map和boost::cons都有O(1)运行时访问权限。
struct generic
{
std::map<std::string, boost::variant<foo, bar, bob, int, double> > _impl;
};
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;
}