【问题标题】:Ensuring coverage for all enum values in map确保覆盖地图中的所有枚举值
【发布时间】:2014-11-05 22:20:58
【问题描述】:

假设我有以下内容:

#include <map>

enum class Thing {Zero, One, Two};

class Metadata {};

std::map<Thing, Metadata> extra_info;

void foo() {
    extra_info[Thing::Zero] = Metadata();
    extra_info[Thing::One] = Metadata();
    extra_info[Thing::Two] = Metadata();
}

我想确保Thing 的所有标签都包含在extra_info 中,以防添加新标签,例如Thing::Three

我考虑总是在末尾有一个标签LastTag,并从0 迭代到LastTag - 2 并验证这些键是否存在于地图中,但这似乎很笨拙。最好在编译时实现这一点,但我认为这根本不可能。

在 C# 中,使用反射来获取所有枚举值,然后遍历这些值是一件简单的事情。我认为这说明我无法使用 C++ 标签找到答案,但我可以找到 Java 和 C# 的答案......这让我觉得这是不可能的。

【问题讨论】:

  • 在使用枚举时使用您指定的“最后一个”方法是很常见的:在最后一个虚拟值成为有效值的最后一个常量。虽然看起来很笨拙,但这是我们一直以来在 C/C++ 中所做的事情,因此采用这种方法有很多先例。
  • 您甚至不必迭代。如果您知道 last 的值是 n,那么您只需检查地图的大小是否等于 n。这将起作用,因为映射需要唯一键并且它只接受有效的枚举类型。

标签: c++ enums


【解决方案1】:

枚举中的标记值已成为许多项目的一部分,用于指示枚举值的数量或将用户可用的枚举范围与系统定义的枚举分隔开。

在您的情况下,您可以利用地图具有唯一键的事实并添加一个标记值(严格来说不是枚举的一部分):

enum class Thing { Zero, One, Two, Three, EndSentinel };

class Metadata {};

std::map<Thing, Metadata> extra_info;
typedef std::map<Thing, Metadata>::size_type map_type;

void foo() {
    // Can't forget these values
    extra_info[Thing::Zero] = Metadata();
    extra_info[Thing::One] = Metadata();
    extra_info[Thing::Two] = Metadata();
    extra_info[Thing::Three] = Metadata();
}

int main() {
    foo();

    assert(extra_info.size() == (map_type)Thing::EndSentinel);
}

Example

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-02
    • 1970-01-01
    • 2019-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多