lts*_*tar 6 c++ arrays indexing enums c++11
std:array当我想引用特定索引时,我想使用 C++ 枚举类作为索引而不调用显式转换。
我还使用 atypedef作为固定大小的std::array.
typedef std::array<int, 3> MyType;
enum class MyEnum {
ENUMERATOR0 = 0,
ENUMERATOR1 = 1,
ENUMERATOR2 = 2,
};
Run Code Online (Sandbox Code Playgroud)
所以不要使用:
MyType my_type = {0};
my_type[static_cast<int>(MyEnum::ENUMERATOR0)] = 42;
Run Code Online (Sandbox Code Playgroud)
我想使用:
my_type[MyEnum::ENUMERATOR0] = 42;
Run Code Online (Sandbox Code Playgroud)
因此,我假设需要重载我的MyType( std::array) 类型的下标运算符。但是,我不知道如何在我的情况下重载下标运算符。为简单起见,我想避免使用类而不是 typedef。我怎样才能做到这一点?
我为此找到了一个很好的解决方案。您既可以使用枚举类作为数组中的索引,也可以通过继承 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);
}
};
Run Code Online (Sandbox Code Playgroud)
你可以像这样使用它:
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
}
Run Code Online (Sandbox Code Playgroud)
您不能覆盖[]不属于您的类型。
请参阅http://en.cppreference.com/w/cpp/language/operators——不能是非operaror[]成员重载。
你可以这样做:
template<class E, class T, std::size_t N=E::count>
struct enum_array: std::array<T, N>{
using base= std::array<T, N>;
constexpr enum_array():base{}{}
template<class A0, class...Args,
std::enable_if_t<!std::is_same<T, std::decay_t<A0>>{}, bool>=true
>
constexpr enum_array(A0&& a0, Args&&...args):base{{std::forward<A0>(a0), std::forward<Args>(args)...}}{}
// using base::operator[]; // -- if you want to expose [size_t] as well
constexpr T& operator[](E const& e){ return base::operator[](static_cast<std::size_t>(e)); }
constexpr T const& operator[](E const& e)const{ return base::operator[](static_cast<std::size_t>(e)); }
};
Run Code Online (Sandbox Code Playgroud)
这是接近的。代替
MyType x={{1,2,3}};
Run Code Online (Sandbox Code Playgroud)
和
enum_array<MyEnum, int> x={1,2,3};
Run Code Online (Sandbox Code Playgroud)
并添加count到MyEnum.