C++中的另一个静态数组初始化
Yet another static array initialization in C++
我在C++中有以下代码(C++11可用(
typedef enum
{
APPLE,
ORANGE,
LAST,
} fruits_t;
template <typename T, size_t size> char (&ArraySizeHelper( T (&)[size]))[size];
#define arraysize(pArray) sizeof(ArraySizeHelper(pArray))
static const char *LOOKUP_TABLE[]
{
"apple", // APPLE
"orange", // ORANGE
};
// Fail the compilation if the lookup table is missing anything
static_assert(arraysize(LOOKUP_TABLE) == LAST, "Update the lookup table");
我希望能够在不更改LOOKUP_TABLE初始化列表的情况下更改枚举中的顺序。
我已经阅读了这个 初始化一个具有一个默认值的普通数组,模板几乎是我需要的,但不完全是。我在元编程上挣扎了半天,仍然不知道该怎么做。
代码中的实际枚举从零开始,包含 20-30 个条目。我考虑过哈希表 - 哈希函数是微不足道的,但初始化问题仍然存在。我在代码中有很多 - 5+ - 这样的查找表。值得奋斗吗?
附言在围绕开关构造的几个答案之后,让我展示一大块真正的代码。这只是一个例子。
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");
}
P.S.2 我在之前的 P.S. 中想说的是,"switch"给了编译器太多的自由。我想确保查找是一个简单的表,而不是一些双索引数组或 if/else 分支
P.S.3 这是初始化数组的另一个示例。数组包含钩子,调用正确的函数非常重要。
typedef struct
{
const int id;
const events_process_t processor;
uint64_t counter;
} events_process_table_t;
static events_process_table_t events_processors[EVENT_ID_LAST] =
{
{EVENT_ID_OPEN , (events_process_t)events_process_open },
{EVENT_ID_OPENAT , (events_process_t)events_process_open },
// and so on for 30 lines
};
static_assert(arraysize(events_processors) == EVENT_ID_LAST, "Update the table of events processors");
void some_code(int event_id)
{
events_process_table_t *table = &events_processors[event_id];
if (event_id == table->id)
{
// Looks alright and I can use the table->processor
// .....
}
}
我认为处理这种情况的最有效方法是使用将枚举值映射到其相应 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(fruits(' 中:
主.cpp:7:12: 警告:未在开关 [-Wswitch] 中处理枚举值"last">
switch (x) {
现场演示
如果使用-Werror
进行编译,则会阻止编译。
鉴于您问题的症结是:
我希望能够在没有 更改LOOKUP_TABLE中的初始化列表。
这是一个非常简单的问题:
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
}
是的,你不能对它做static_assert()
。 但你不需要。 许多现代编译器甚至在 switch(( 中未处理enum fruits_t
之一时会警告您。
对于 30 个左右的值,函数会变得有点冗长,但列表必须很长,哈希表才会开始超过 switch((。
这比涉及宏的模板化函数更具可读性。 如果你需要它来进行大学作业或其他什么,那就好了。 但是上述方法在 C 和 C++ 中都有效,不需要 C++11。
只是试图保持简单。
- C++使用整数的压缩数组初始化对象
- C++17中函数模板中的静态数组初始化(MSVC 2019)
- 从另一个静态常量数组初始化静态常量数组(只需少量计算)
- 在 Python 和 c++ 2d 数组初始化之间.这是怎麽?为什么呢?
- 字节数组初始化会导致 DirectX 崩溃
- 使用 new 和 值进行数组初始化,但没有显式数量的元素
- 运行时C++数组初始化问题
- 使用带有参数包的数组的成员数组初始化类
- 仅通过C++中数组初始化的不同方法,即可在同一输入上获得两个不同的答案
- C++ 2 个指针数组初始化 C2440
- C++结构字符数组初始化
- C++中的多维数组初始化
- constexpr数组初始化
- C++引物动态数组初始化程序的数目超过大小
- 使用std::index_sequence对std::数组初始化进行包扩展
- 当 std 数组初始化太小时,C++会引发错误吗?
- 如何确定结构数组初始化的大小?
- Qt并发错误:数组初始化需要大括号括起来的初始值设定项列表
- 此代码中的数组初始化样式是什么?这是标准的吗?
- C++ 使用数组初始化时的 STL 向量内存管理