我想将(作用域)枚举的值映射到其他一些值。例如,这里我将 Color
映射到其他枚举 Group
:
enum class Color {
Red, Green, Blue, Cyan, Magenta, Yellow, White, Black,
COUNT // Needed to know the number of items
};
enum class Group {
Primary, Secondary, Neutral
};
Group GetGroupOfColor(Color color); // Mapping function I'm going to implement
我想确保如果任何人更改 Color
枚举中的元素数量,此函数将无法编译。
我想出了解决这个问题的唯一方法:
Group GetGroupOfColor(Color color)
{
static const Group color2group[] = {
Group::Primary, // Red
Group::Primary, // Green
Group::Primary, // Blue
Group::Secondary, // Cyan
Group::Secondary, // Magenta
Group::Secondary, // Yellow
Group::Neutral, // White
Group::Neutral // Black
};
static_assert(ARRAY_SIZE(color2group) == size_t(Color::COUNT), "DEADBEEF!");
auto index = size_t(color);
assert(index < size_t(Color::COUNT));
return color2group[index];
}
其中ARRAY_SIZE
可以像下面这样实现:
template <typename T, size_t N>
constexpr size_t ARRAY_SIZE(T(&)[N])
{
return N;
}
这个实现满足了我的要求,但它有很多缺点:
- 在
Color
枚举中添加这个丑陋的COUNT
项(最让我烦恼) - 如果有人重新订购
Color
的商品,则会失败,且不会提示 - 不适用于不连续的枚举,即具有显式赋值的枚举(这并不重要)
我的问题是,有没有办法改进这个实现?也许有一些我什至没有想到的不同方法。也许有它自己的缺点,我会觉得不那么烦人。
另请参阅:
最佳答案
我会使用 switch
语句。
switch (colour) {
case Colour::Red: return Group::Primary;
//...
case Colour::Black: return Group::Neutral;
}
return Group::Invalid; // or throw, assert, or whatever.
这应该可以满足您的所有需求:
Adds this ugly
COUNT
item inColor enum
(bothers me most)
不需要,每个枚举器只需一个case
。
Will fail silently if someone reorders items of
Color
每个 case
都是显式命名的,因此每个枚举器的值并不重要(只要它们是唯一的;但如果不是这样,您会收到错误)。
Not applicable for not-continuous enums
同样,命名的 case
语句并不关心实际值。
if anyone changes the number of elements in
Color enum
, this function will fail to compile
虽然不能保证,但大多数编译器应该能够警告开关中是否存在未处理的枚举器(只要没有 default
分支)。对于 GCC,该选项是 -Wswitch
(包含在 -Wall
中),如果您希望它导致失败,还可以加上 -Werror
。
关于c++ - 枚举映射对重构具有鲁棒性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28602114/