代码之家  ›  专栏  ›  技术社区  ›  Hayden Piper

枚举类作为数组索引

  •  24
  • Hayden Piper  · 技术社区  · 8 年前

    我列举如下:

    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 ,但我觉得这应该管用,我想学习如何做到这一点。

    有任何回应/建议吗?

    9 回复  |  直到 2 年前
        1
  •  25
  •   Simple    8 年前

    范围 enum 第二节( enum class )不能隐式转换为整数。您需要使用 static_cast :

    SDL_Surface*KEY_PRESS_SURFACES[static_cast<int>(KeyPressSurfaces::KEY_PRESS_SURFACE_TOTAL)];
    
        2
  •  23
  •   Community THelper    7 年前

    您可以将 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 作用 here

        3
  •  4
  •   knivil    8 年前

    拆下 class 关键字或显式转换为整型。

        4
  •  3
  •   eric    4 年前

    在其他响应的基础上,另一种选择是一个简单的模板化类,它封装了一个c样式数组。在下面的EnumArray示例中,任何 enum class 用一个 kMaxValue 可以用作索引。

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

    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;
    }
    
        5
  •  3
  •   Stefan    3 年前

    您可以处理阵列:

    /** \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)); }
    };
    
        6
  •  2
  •   GeorgeMakarov    2 年前

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

    namespace KeyPressSurfaces
    {
        enum
        {
            DEFAULT = 0,
            UP,
            DOWN,
            LEFT,
            RIGHT,
            TOTAL
        };
    }
    
    SDL_Surface* KEY_PRESS_SURFACES[KeyPressSurfaces::TOTAL];
    
        7
  •  0
  •   Joe'    2 年前

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

    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)];
    }
    
    

    现在,您可以使用enum类清晰地获取曲面:

    // assignment
    getKeyPressSurface(KeyPressSurface::UP) = SDL_LoadBMP("lamp.bmp");
    // or get a value
    SDL_Surface *currentSurface = getKeyPressSurface(KeyPressSurface::RIGHT);
    
        8
  •  0
  •   Burak    2 年前

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

    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];
    
        9
  •  -3
  •   parsley72    7 年前

    或者,您可以更换 array 用一个 map ,这也意味着你可以摆脱 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;