我正在尝试创建类似列表的内容。但是,列表的不同实例可以具有不同数量的条目,并且条目的类型基于用户给出的输入。例如,用户声明他们希望列表中每个条目的结构包含int id,std :: string名称,double metricA和long metricB。根据此输入,将创建以下内容:
struct some_struct {
int id;
std::string name;
double metricA;
long metricB;
}
list<some_struct> some_list;
用户输入可以从文件中读取,在屏幕上输入等。另外,它们是some_struct中可变数量的条目。换句话说,它可能有上面列出的条目,它可能只有2个,或者它可能有10个完全不同的条目。有没有办法创建这样的结构?
此外,能够将比较运算符应用于some_struct的每个成员是必须的。我可以使用boost :: any来存储数据,但这会产生比较运算符的问题,并且还会产生比理想情况更多的开销。
答案 0 :(得分:4)
C ++是一种强类型语言,这意味着您必须声明您的数据结构类型。为此,您不能声明具有任意数量或类型成员的struct
,必须事先了解它们。
当然,现在有办法在C ++中处理这些问题。仅举几例:
std::map
或std::unordered_map
)创建“表格”而不是结构。将字符串映射到字符串,即将名称映射到值的字符串表示,并将它们解释为您的心。boost::any
。可能有很多其他方法可以做到这一点,因为有C ++程序员。
答案 1 :(得分:2)
有许多方法可以解决具有不同成员的数据结构问题,而这最好的方法很大程度上取决于它将如何使用。
最明显的是使用继承。您可以从基类中获得所有可能性:
struct base_struct {
int id;
std::string name;
};
list<base_struct*> some_list;
struct some_struct : public base_struct {
double metricA;
};
struct some_other_struct : public base_struct {
int metricB;
};
base_struct *s1 = new some_struct;
s1->id = 1;
// etc
base_struct *s2 = new some__other_struct;
s2->id = 2;
// etc
some_list.push_back(s1);
some_list.push_back(s2);
棘手的一点是,你必须确保当你获得元素时,你的情况恰如其分。 dynamic_cast
可以通过类型安全的方式执行此操作:
some_struct* ss = dynamic_cast<some_struct*>(some_list.front());
您可以使用type_info
投标前查询名称:
typeid(*some_list.front()).name();
请注意,这两者都需要使用RTTI进行构建,这通常是正常的,但并不总是因为RTTI具有性能成本并且可能会使内存占用空间膨胀,尤其是在广泛使用模板的情况下。
在之前的项目中,我们使用boost any处理了类似的事情。 any
的优点是它允许您混合不是彼此派生的类型。回想起来,我不确定我是否会再次这样做,因为它使代码在运行时有点太容易失败,因为类型检查在此之前被推迟。 (对于dynamic_cast
方法也是如此。
在糟糕的旧C日,我们用union
:
struct base_struct {
int id;
std::string name;
union { // metricA and metricB share memory and only one is ever valid
double metricA;
int metricB;
};
};
同样,你有一个问题,你必须自己处理确保它是正确的类型。
在STL之前的时代,许多容器系统被编写为采用void*
,再次要求用户知道何时投射。理论上,你仍然可以通过说list<void*>
来做到这一点,但是你无法查询类型。
编辑:从不,永远使用void*
方法!
答案 2 :(得分:0)
我最终使用了一个带有boost :: variant的列表。性能远远优于使用boost :: any。它是这样的:
#include <boost/variant/variant.hpp>
#include <list>
typedef boost::variant< short, int, long, long long, double, string > flex;
typedef pair<string, flex> flex_pair;
typedef list< flex_pair > row_entry;
list< row_entry > all_records;