在地图

问题描述:

所有枚举值确保覆盖面说我有以下几点:在地图

#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,并从0LastTag - 2迭代并验证这些密钥是否存在于地图中,但这看起来很奇怪。在编译时完成这一任务的方法是最好的,但我可以看到这完全不可能。

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

+1

使用枚举时,这种情况很常见使用您指定的“最后”方法:在最后一个虚拟值成为有效值的一个尾部的常量。虽然看起来很烂,但这是我们从C/C++永远做起的事情,所以采取这种方法有很多先例。 – cdhowie 2014-11-05 22:29:48

+1

你甚至不需要迭代。如果你知道last的值是'n',那么你可以检查map的大小是否等于'n'。这将工作,因为地图需要唯一的键,它只会接受有效的枚举类型。 – 2014-11-05 23:08:21

枚举中的Sentinel值已成为许多项目的一部分,用于指示枚举值的数量或从系统定义的枚举中为用户可用枚举的范围划界。

你的情况,你可以利用一个地图都有唯一的密钥的事实,并添加一个标记值(严格不枚举的一部分):

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