当我想引用特定索引时,我想使用C ++枚举类作为std:array索引而不调用显式转换。
我还使用了一个固定大小的std :: array的typedef。
typedef std::array<int, 3> MyType;
enum class MyEnum {
ENUMERATOR0 = 0,
ENUMERATOR1 = 1,
ENUMERATOR2 = 2,
};
所以不要使用:
MyType my_type = {0};
my_type[static_cast<int>(MyEnum::ENUMERATOR0)] = 42;
我想用:
my_type[MyEnum::ENUMERATOR0] = 42;
因此,我假设需要重载myType(std :: array)类型的下标运算符。但是,我无法弄清楚,在我的情况下如何重载下标运算符。为简单起见,我想避免使用类而不是typedef。 我怎么能这样做?
答案 0 :(得分:1)
您不能在您不拥有的类型上覆盖[]
。
请参阅http://en.cppreference.com/w/cpp/language/operators - operaror[]
不能非成员重载。
你可以这样做:
struct MyType: std::array<int, 3>{
using base= std::array<int, 3>;
constexpr MyType():base{}{}
template<class A0, class...Args,
std::enable_if_t<!std::is_same<MyType, std::decay_t<A0>>{}, bool>=true
>
constexpr MyType(A0&& a0, Args&&...args):base{{std::forward<A0>(a0), std::forward<Args>(args)...}}{}
using base::operator[];
constexpr int& operator[](MyEnum e){ return operator[](static_cast<std::size_t>(e)); }
constexpr int const& operator[](MyEnum e)const{ return operator[](static_cast<std::size_t>(e)); }
};
这很接近。取代
MyType x={{1,2,3}};
与
MyType x={1,2,3};
答案 1 :(得分:1)
我为此找到了一个很好的解决方案。您既可以将枚举类用作数组中的索引,又可以通过子类化std :: array并覆盖其operator []方法来获得确保类型安全(即,防止使用错误的枚举类型作为索引)的额外好处。
这里是一个例子。
您可以这样定义enum_array:
#include <array>
// this is a new kind of array which accepts and requires its indices to be enums
template<typename E, class T, std::size_t N>
class enum_array : public std::array<T, N> {
public:
T & operator[] (E e) {
return std::array<T, N>::operator[]((std::size_t)e);
}
const T & operator[] (E e) const {
return std::array<T, N>::operator[]((std::size_t)e);
}
};
您可以像这样使用它:
int main() {
enum class Fruit : unsigned int {
Apple,
Kiwi
};
enum class Vegetable : unsigned int {
Carrot,
Potato
};
// Old way:
std::array<int, 3> old_fruits;
std::array<int, 3> old_veggies;
old_fruits[(int)Fruit::Apple] = 3; // compiles but "ugly"
old_veggies[(int)Vegetable::Potato] = 7; // compiles but "ugly"
old_fruits[(int)Vegetable::Potato] = 3; // compiles but shouldn't compile!
old_fruits[2] = 6; // compiles but may or may not be desirable
// New way:
enum_array<Fruit, int, 3> fruits;
enum_array<Vegetable, int, 3> veggies;
fruits[Fruit::Apple] = 3;
veggies[Vegetable::Potato] = 7;
// fruits[Vegetable::Potato] = 3; // doesn't compile :)
// fruits[2] = 6; // doesn't compile
// fruits[(int)Fruit::Apple] = 3; // doesn't compile
}
答案 2 :(得分:0)
我不喜欢enum class
的当前行为。在我确实需要在指定枚举值时强制使用枚举名称的情况下,我使用以下代码。
//Utilities.hpp
#define SETUP_ENUM_STRUCT_ASSIGNMENTS(EnumStruct, EType) \
EType val; \
EnumStruct(){} \
EnumStruct(EType p_eVal):val(p_eVal) {} \
operator EType () const { return val; } \
void operator=(EType p_eVal) { val = p_eVal; }
#define ENUM_STRUCT(EName, ...) \
struct EName { \
enum Type { \
__VA_ARGS__ \
}; \
SETUP_ENUM_STRUCT_ASSIGNMENTS(EName, Type) \
};
//main.cpp
int main(){
ENUM_STRUCT( EFruit, //<--this line is weird and looks unusual
APPLE, // for enum definition, but this tool
GRAPES, // does the work I need so it's OK for
ORANGE, // me despite the code weirdness.
COUNT
)
std::array<int, EFruit::COUNT> listF; //<--no need for any type-casting.
listF[EFruit::APPLE] = 100; //<--looks cleaner like enum class with
// no type restriction.
return 0;
}
在特殊情况下,我使用ENUM_STRUCT
宏主要是为了提高可读性(这对调试很有帮助)。在大多数情况下,我使用普通的enum
。由于限制,我很少使用enum class
。
答案 3 :(得分:0)
信誉不足,因此我无法发表评论... 在jordi的解决方案上,替换旧式的强制类型转换:
(std::size_t)e
具有新样式:
static_cast<std::size_t>(e)
这将避免编译警告...
答案 4 :(得分:0)
您可以使用 findDOMNode
模拟 enum
:
class
然后你可以像这样使用它:
struct MyEnum {
enum {
ENUMERATOR0 = 0,
ENUMERATOR1 = 1,
ENUMERATOR2 = 2,
} _val;
constexpr MyEnum(decltype(_val) value) noexcept :
_val{value}
{
}
constexpr explicit MyEnum(int value) noexcept :
_val{static_cast<decltype(_val)>(value)}
{
}
[[nodiscard]] constexpr operator int() const noexcept
{
return _val;
}
};