基本上,我希望MyClass持有一个Hashmap将字段名(字符串)映射到任何类型的值。为此,我编写了一个单独的MyField类来保存类型和值信息。
这是我目前所掌握的:
template <typename T>
class MyField {
T m_Value;
int m_Size;
}
struct MyClass {
std::map<string, MyField> fields; //ERROR!!!
}
但是正如您所看到的,映射声明失败了,因为我没有为MyField提供类型参数...
所以我想应该是
std::map< string, MyField<int> > fields;
或
std::map< string, MyField<double> > fields;
我有什么办法可以做到这一点吗?
Blindy的答案很好(+1),但只是为了完成答案:还有一种方法可以在没有库的情况下完成,通过使用动态继承:
class MyFieldInterface
{
int m_Size; // of course use appropriate access level in the real code...
~MyFieldInterface() = default;
}
template <typename T>
class MyField : public MyFieldInterface {
T m_Value;
}
struct MyClass {
std::map<string, MyFieldInterface* > fields;
}
优点:
缺点:
因此,如果可以,请使用boost::any或boost::variant作为默认值,只有在其他情况下才考虑此选项。
struct MyClass {
std::map<string, std::unique_ptr<MyFieldInterface> > fields; // or shared_ptr<> if you are sharing ownership
}
然而,还有一个潜在的问题:
它强制您使用new/delete(或make_unique/shared)创建对象。这意味着实际的对象是在空闲存储区(堆)中由分配器提供的任何位置(主要是默认位置)创建的。因此,由于缓存丢失,查看对象列表的速度往往不如可能的快。
如果您关心尽可能快地循环此列表的性能(如果不关心,则忽略以下内容),那么您最好使用boost::variant(如果您已经知道将要使用的所有具体类型)或使用某种类型擦除的多态容器。
下面是一个例子(图片来自那里):http://bannalia.blogspot.fr/2014/05/fast-polymorphic-collections.html
但是,如果您需要保持插入对象的顺序,那么这种技术就不受欢迎了。
无论如何,都有几种可能的解决方案,这在很大程度上取决于您的需求。如果您对您的案例没有足够的经验,我建议使用我在示例中首先解释的简单解决方案或boost::any/variant。
作为对这个答案的补充,我想指出一些非常好的博客文章,这些文章总结了您可以使用的所有C++类型擦除技术,并附上评论和优缺点:
我有如下数据表示: 我需要在我的C应用程序中访问这些数据。我还需要能够通过可变键名关联地访问项目;例如: A<code>std::vector 我有办法做到这一点吗?我确实更喜欢使用向量和地图,但我对其他解决方案持开放态度,只要我可以关联地访问数据项。 使用这里描述的模板是可行的方法吗?
以下代码片段适用于Visual Studio 2008,但不适用于Visual Studio 2010。 用法 我得到以下错误: 1个 如果用typedef int MyValueType替换typedef STD::tr1::tuple myvalue type,则有效。 提前感谢您。
问题内容: 是否有与C ++等效的Java Map keySet()? Java 方法返回“此映射中包含的键的设置视图”。 问题答案: 也许以下可能有用: 使用STL兼容序列(例如std :: vector,std :: deque或std :: list)的 make_key_set 函数的重载可以如下所示:
问题内容: 我正在寻找具有C ++ std :: map的通常实现特征的Java类(据我了解,这是一个自平衡二进制搜索树): 插入/删除/搜索的O(log n)性能 每个元素均由唯一键和映射值组成 按键遵循严格的弱顺序 我正在寻找带有开源或设计文档的实现;我可能最终会放弃对原始键/值的支持。 这个问题的风格类似于:std :: deque的Java等效 ,其答案是“ Java Primitive
问题内容: 是否可以在条件表达式包含任意类类型的对象的GDB中设置条件断点? 我需要在函数内部设置一个断点,条件将检查条件是否是对象的成员字符串变量等于“ foo”。因此,类似: 但这不起作用。GDB是否只允许在基本类型和char *类型上使用条件断点?有什么办法可以在非原始类型上设置条件断点? 问题答案: 有什么办法可以在非原始类型上设置条件断点? 是的,一种实现方法是将非原始类型转换为原始类型
我目前在C#中面临一个问题,我认为可以使用存在类型来解决这个问题。然而,我真的不知道它们是否可以在C#中创建,或者模拟(使用其他构造)。