C++; 我在C++中有以下代码(C++ 11可用)< /P> typedef枚举 { 苹果, 橙色 最后,, }水果; 模板字符(&ArraySizeHelper(T(&)[size]))[size]; #定义arraysize(阵列)大小(ArraySizeHelper(阵列)) 静态常量字符*查找表[] { “苹果”//苹果 “橙色”,//橙色 }; //如果查找表缺少任何内容,则编译失败 静态_断言(arraysize(LOOKUP_TABLE)=LAST,“更新查找表”);

C++; 我在C++中有以下代码(C++ 11可用)< /P> typedef枚举 { 苹果, 橙色 最后,, }水果; 模板字符(&ArraySizeHelper(T(&)[size]))[size]; #定义arraysize(阵列)大小(ArraySizeHelper(阵列)) 静态常量字符*查找表[] { “苹果”//苹果 “橙色”,//橙色 }; //如果查找表缺少任何内容,则编译失败 静态_断言(arraysize(LOOKUP_TABLE)=LAST,“更新查找表”);,c++,arrays,static,initialization,C++,Arrays,Static,Initialization,我希望能够在不更改LOOKUP_表中的初始化列表的情况下更改枚举中的顺序 我读过这篇文章,模板几乎是我所需要的,但不完全是。我与元编程斗争了半天,仍然不知道如何做 代码中的实际枚举从零开始,包含20-30个条目。我考虑过一个哈希表——哈希函数很简单,但初始化问题仍然存在。我在代码中有许多这样的-5+查找表。值得奋斗吗 另外,在对switch构造进行了一些回答之后,让我展示一段真正的代码。这只是一个例子 typedef enum { EVENTS_STATISTICS_COLLECTOR_

我希望能够在不更改LOOKUP_表中的初始化列表的情况下更改枚举中的顺序

我读过这篇文章,模板几乎是我所需要的,但不完全是。我与元编程斗争了半天,仍然不知道如何做

代码中的实际枚举从零开始,包含20-30个条目。我考虑过一个哈希表——哈希函数很简单,但初始化问题仍然存在。我在代码中有许多这样的-5+查找表。值得奋斗吗

另外,在对switch构造进行了一些回答之后,让我展示一段真正的代码。这只是一个例子

typedef enum
{
    EVENTS_STATISTICS_COLLECTOR_POOL_TIMEOUT            ,
    EVENTS_STATISTICS_COLLECTOR_POOL_FAILED             ,
    EVENTS_STATISTICS_COLLECTOR_SENT_TO_PIPELINE        ,

    // 50 entries like this 
    EVENTS_STATISITCS_LAST                              ,
} events_statistics_t;

uint64_t events_statistics[EVENTS_STATISITCS_LAST];
const char *event_statistics_names[] = {
    "collector_pool_timeout         ",
    "collector_pool_failed          ",
    "collector_sent_to_pipeline     ",
    // and so on ...
};

static inline void events_statistics_bump_counter(events_statistics_t counter)
{
    events_statistics[counter]++;
}

// The actual function is a generic one which prints arbitrary pairs
// But this one gives an idea
void print_statistics()
{
    int col = 0;
    static const int COLUMNS = 3;
    printf("\n");
    for (int i = 0;i < EVENTS_STATISITCS_LAST;i++)
    {
        printf("%-30s %9lu", event_statistics_names[i], events_statistics[i]);
        col++;
        if ((col % COLUMNS) == 0)
            printf("\n");
        else
            printf("%4s", "");
    }
    if ((col % COLUMNS) != 0)
        printf("\n");
}

我认为处理这种情况最有效的方法是使用一个函数将枚举值映射到对应的C字符串:

enum class fruits { apple, orange, last };

char const* show(fruits x) {
    switch (x) {
        case fruits::apple: return "apple";
        case fruits::orange: return "orange";
        case fruits::last: return "last";
    }
    assert(false);
    return nullptr;
}

此时,如果您忘记在
show
中定义
fruits::last
的字符串,大多数编译器都会发出如下警告:

main.cpp:在函数“const char*show(水果)”中:

main.cpp:7:12: 警告:枚举值“last”未在开关[-Wswitch]中处理

 switch (x) {


如果您使用
-Werror
编译,则会阻止编译。

鉴于您问题的关键是:

我希望能够更改枚举中的顺序,而无需 更改LOOKUP_表中的初始化列表

这是一个非常简单的问题:

const char *fruityLookup(fruits_t f)
{
    switch (f)
    {
        case APPLE:  return "apple";
        case ORANGE: return "orange";
        case DURIAN: return "Woah!";
        // do not add a default
    }
    assert(false); // check definition of fruits_t
}
是的,您不能对其执行
静态断言()。但是你不需要。许多现代编译器甚至会在switch()中未处理
enum fruit
中的一个时向您发出警告

对于30个左右的值,函数将有点冗长,但列表必须相当长,哈希表才能开始比switch()快

这比包含宏的模板化函数更具可读性。如果你需要它来做大学作业或其他什么的,那好吧。但以上两个工作都在C和C++中,不需要C++ 11。
只是尽量保持简单。

@YuHao模板编程和/或预处理器宏显然是解决问题的方法,但具体如何。C++不允许初始化数组,比如C99 {[Apple ]:“Apple”,[Orange ]:“橙色”},你对EnUM和它的值的字符串表示有什么用途?@在真实代码中,查找表中的数据是一个非平凡对象(内存池)。代码解析传入事件,具体取决于事件标识符选择内存池并从池中分配对象。枚举是事件标识符。在另一个表中,字符串是调试计数器的描述(~50个计数器)。调试计数器是调试计数器数组的一部分。我有一个print函数,它在数组上循环并打印pairs值:“description”。@larytet-内存池中的和项不是直接归结为一个地址吗?我想继续查找表。使用switch可能会导致代码优化程度较低,这取决于实际的枚举。我在15分钟前发布了相同的精确解。这个答案补充了什么?更不用说在
switch
语句中有一个默认子句,编译器会警告缺少枚举值。@shoe-是,但当我开始键入时,没有答案。虽然默认设置很好。@kingsley你的答案不配-1我解决了这个问题。在数组和开关之间,我将保留数组。性能更重要,而且阵列看起来更好。我真的很想在不影响性能的情况下处理枚举中的漏洞——一个哈希表。这个答案仍然存在问题。其中很少有问题可以通过编译代码来解决。
const char *fruityLookup(fruits_t f)
{
    switch (f)
    {
        case APPLE:  return "apple";
        case ORANGE: return "orange";
        case DURIAN: return "Woah!";
        // do not add a default
    }
    assert(false); // check definition of fruits_t
}