在上述 class 的 std::map 中使用 class 成员作为键

Using class member as key in a std::map of said class

我有一个 class 和一个枚举 class 成员变量,旨在用作实例化对象的描述,永远不会有两个相同类型的实例化对象,示例:

class A
{
   enum class Type { Type1, Type2, ...} type;
}

我想将所有实例化的对象存储在一个集合中,以便于根据类型进行访问,所以我认为 map 比较合适:

class B
{
   std::map<A::Type, A> components;
}

但是,有些东西告诉我这不是很好的设计,因为我有效地复制了相同的数据,即使用 class (A) 成员变量 (type)作为指向也包含相同信息的值(class A 的对象)的键。另一种选择是不将枚举用作 class A 成员变量,而是在 class B[=24= 中定义该枚举] 并且仅将其用作密钥。 有什么建议吗?

让我们考虑地图的主要特征

  • 唯一键
  • 关于键的排序
  • 键是 const,值不是
  • 键与映射值分开存储

您的要求与上一条相反,所以现在您可以考虑与其他人做出什么样的妥协。

  • std::set<A,CustomComparator>

使用自定义比较器,您可以确保可以存储在值中的唯一键,并且排序可以与地图相同。但是元素是const。您可以使用 mutable 但这会绕过 const-correctness,应谨慎使用。

  • std::vector<A>

这是最灵活的,但您需要手动处理从地图上获得的几乎所有内容。如果只填充向量一次然后只访问元素是可行的,因为这样你就需要检查唯一性并对元素进行一次排序。

  • 一些非标准容器

Jarod42 建议增强侵入性 set。可能还有其他符合您需要的非标准容器。

  • 留在std::map<A::type,A>

如果键只是一个枚举值,那么将键存储两次是一个简单的解决方案,但需要一些成本,但允许您在要使用的容器时使用 map

  • 首先不将密钥存储在 mapped_values 中

当 mapped_values 仅存储在地图中而不在地图外使用时,这实际上是最干净的解决方案。当您仍然需要 mapped_values 和地图外的键时,您可以使用 std::pair<type::A,A>.