枚举类作为数组索引

enum class as array index

本文关键字:数组 索引 枚举      更新时间:2023-10-16

我做了一个枚举:

enum class KeyPressSurfaces {
    KEY_PRESS_SURFACE_DEFAULT,
    KEY_PRESS_SURFACE_UP,
    KEY_PRESS_SURFACE_DOWN,
    KEY_PRESS_SURFACE_LEFT,
    KEY_PRESS_SURFACE_RIGHT,
    KEY_PRESS_SURFACE_TOTAL
};

后来我尝试在下面键入定义一个数组,但我收到了错误,size of array 'KEY_PRESS_SURFACES' has non-integral type 'KeyPressSurfaces'

SDL_Surface*KEY_PRESS_SURFACES[KeyPressSurfaces::KEY_PRESS_SURFACE_TOTAL];

我很好地理解了错误,但我不知道将KeyPressSurfaces移动到何处以限定枚举中的常量。

我也意识到我可以用enum而不是enum class,但我觉得这应该有效,我想学习如何做到这一点。

任何回应/建议?

作用

enum s(enum class)不能隐式转换为整数。您需要使用static_cast

SDL_Surface*KEY_PRESS_SURFACES[static_cast<int>(KeyPressSurfaces::KEY_PRESS_SURFACE_TOTAL)];
您可以使用

模板函数将enum转换为int,您将获得更具可读性的代码:

#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
enum class KeyPressSurfaces: int {
    KEY_PRESS_SURFACE_DEFAULT,
    KEY_PRESS_SURFACE_UP,
    KEY_PRESS_SURFACE_DOWN,
    KEY_PRESS_SURFACE_LEFT,
    KEY_PRESS_SURFACE_RIGHT,
    KEY_PRESS_SURFACE_TOTAL
};
template <typename E>
constexpr typename std::underlying_type<E>::type to_underlying(E e) {
    return static_cast<typename std::underlying_type<E>::type>(e);
}

int main() {
    KeyPressSurfaces val = KeyPressSurfaces::KEY_PRESS_SURFACE_UP;
    int valInt = to_underlying(val);
    std::cout << valInt << std::endl;
    return 0;
}

我在这里to_underlying功能

您可以在数组上工作:

/** brief It's either this or removing the "class" from "enum class" */
template <class T, std::size_t N>
struct EnumClassArray : std::array<T, N>
{
    template <typename I>
    T& operator[](const I& i) { return std::array<T, N>::operator[](static_cast<std::underlying_type<I>::type>(i)); }
    template <typename I>
    const T& operator[](const I& i) const { return std::array<T, N>::operator[](static_cast<std::underlying_type<I>::type>(i)); }
};

删除 class 关键字或显式转换为整型类型。

在其他响应的基础上,另一种选择是包装 c 样式数组的简单模板化类。通过下面的 EnumArray 示例,任何带有 kMaxValueenum class都可以用作索引。

在我看来,提高的可读性值得引入模板。

template <class IndexType, class ValueType>
class EnumArray {
 public:  
  ValueType& operator[](IndexType i) { 
    return array_[static_cast<int>(i)];
  }
  const ValueType& operator[](IndexType i) const {
    return array_[static_cast<int>(i)];
  }
  int size() const { return size_; }
 private:
  ValueType array_[static_cast<int>(IndexType::kMaxValue) + 1];
  int size_ = static_cast<int>(IndexType::kMaxValue) + 1;
}; 
enum class KeyPressSurfaces {
    KEY_PRESS_SURFACE_DEFAULT,
    KEY_PRESS_SURFACE_UP,
    KEY_PRESS_SURFACE_DOWN,
    KEY_PRESS_SURFACE_LEFT,
    KEY_PRESS_SURFACE_RIGHT,
    KEY_PRESS_SURFACE_TOTAL,
    kMaxValue = KEY_PRESS_SURFACE_TOTAL
};
int main() {
    EnumArray<KeyPressSurfaces, int> array;
    array[KeyPressSurfaces::KEY_PRESS_SURFACE_DEFAULT] = 5;
    std::cout << array[KeyPressSurfaces::KEY_PRESS_SURFACE_DEFAULT] << std::endl;
    return 0;
}

您可以使用命名空间和匿名枚举。因此,您可以摆脱这些丑陋的前缀并使用枚举项作为索引。

namespace KeyPressSurfaces
{
    enum
    {
        DEFAULT = 0,
        UP,
        DOWN,
        LEFT,
        RIGHT,
        TOTAL
    };
}
SDL_Surface* KEY_PRESS_SURFACES[KeyPressSurfaces::TOTAL];

使用结构成员而不是枚举。

struct KeyPressSurfaces {
    static constexpr int KEY_PRESS_SURFACE_DEFAULT = 0;
    static constexpr int KEY_PRESS_SURFACE_UP= 1;
    static constexpr int KEY_PRESS_SURFACE_DOWN = 2;
    static constexpr int KEY_PRESS_SURFACE_LEFT = 3;
    static constexpr int KEY_PRESS_SURFACE_RIGHT = 4;
    static constexpr int KEY_PRESS_SURFACE_TOTAL = 5;
};

或者,将它们放在具有相同逻辑的命名空间中,您可以从中受益 using namespace .

namespace KeyPressSurfaces {
    constexpr int KEY_PRESS_SURFACE_DEFAULT = 0;
    constexpr int KEY_PRESS_SURFACE_UP= 1;
    constexpr int KEY_PRESS_SURFACE_DOWN = 2;
    constexpr int KEY_PRESS_SURFACE_LEFT = 3;
    constexpr int KEY_PRESS_SURFACE_RIGHT = 4;
    constexpr int KEY_PRESS_SURFACE_TOTAL = 5;
}
SDL_Surface* KEY_PRESS_SURFACES[KeyPressSurfaces::KEY_PRESS_SURFACE_TOTAL];

除了当前接受的答案之外,您还可以编写一个函数来获取对表面的引用:

enum class KeyPressSurface
{
    DEFAULT,
    UP,
    DOWN,
    LEFT,
    RIGHT,
    TOTAL
};
// This is using static_cast like the accepted answer
std::array<SDL_Surface *, static_cast<int>(KeyPressSurface::TOTAL)> keyPressSurfaces;
// Function to get a reference to a surface
SDL_Surface *&getKeyPressSurface(KeyPressSurface surface)
{
    return keyPressSurfaces[static_cast<int>(surface)];
}

现在,您可以使用枚举类干净地获取表面:

// assignment
getKeyPressSurface(KeyPressSurface::UP) = SDL_LoadBMP("lamp.bmp");
// or get a value
SDL_Surface *currentSurface = getKeyPressSurface(KeyPressSurface::RIGHT);
或者

你可以用map替换你的array,这也意味着你可以摆脱KEY_PRESS_SURFACE_TOTAL

enum class KeyPressSurfaces {
    KEY_PRESS_SURFACE_DEFAULT,
    KEY_PRESS_SURFACE_UP,
    KEY_PRESS_SURFACE_DOWN,
    KEY_PRESS_SURFACE_LEFT,
    KEY_PRESS_SURFACE_RIGHT
};
std::map<KeyPressSurfaces, SDL_Surface*> KEY_PRESS_SURFACES;