diff --git a/src/enum_set.h b/src/enum_set.h index c26f56306..ea6e90b40 100644 --- a/src/enum_set.h +++ b/src/enum_set.h @@ -11,10 +11,17 @@ template struct enum_info_t {}; +/// \return the count of an enum. template -class enum_set_t : private std::bitset(enum_info_t::count)> { +constexpr size_t enum_count() { + return static_cast(enum_info_t::count); +} + +/// A bit set indexed by an enum type. +template +class enum_set_t : private std::bitset()> { private: - using super = std::bitset(enum_info_t::count)>; + using super = std::bitset()>; static size_t index_of(T t) { return static_cast(t); } explicit enum_set_t(unsigned long raw) : super(raw) {} @@ -43,6 +50,21 @@ class enum_set_t : private std::bitset(enum_info_t::count bool operator!=(const enum_set_t &rhs) const { return super::operator!=(rhs); } }; +/// An array of Elem indexed by an enum class. +template +class enum_array_t : public std::array()> { + using super = std::array()>; + using base_type_t = typename std::underlying_type::type; + + static int index_of(T t) { return static_cast(t); } + + public: + Elem &at(T t) { return super::at(index_of(t)); } + const Elem &at(T t) const { return super::at(index_of(t)); } + Elem &operator[](T t) { return super::operator[](index_of(t)); } + const Elem &operator[](T t) const { return super::operator[](index_of(t)); } +}; + /// A counting iterator for an enum class. /// This enumerates the values of an enum class from 0 up to (not including) count. /// Example: @@ -81,5 +103,5 @@ class enum_iter_t { public: iterator_t begin() const { return iterator_t{0}; } - iterator_t end() const { return iterator_t{static_cast(enum_info_t::count)}; } + iterator_t end() const { return iterator_t{static_cast(enum_count())}; } }; diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index f3c49128c..7b02115c0 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -318,6 +318,16 @@ static void test_enum_set() { do_test(static_cast(test_enum::COUNT) == idx); } +static void test_enum_array() { + say(L"Testing enum array"); + enum_array_t es{}; + do_test(es.size() == enum_count()); + es[test_enum::beta] = "abc"; + do_test(es[test_enum::beta] == "abc"); + es.at(test_enum::gamma) = "def"; + do_test(es.at(test_enum::gamma) == "def"); +} + /// Test sane escapes. static void test_unescape_sane() { const struct test_t { @@ -5115,6 +5125,7 @@ int main(int argc, char **argv) { if (should_test_function("env_vars")) test_env_vars(); if (should_test_function("str_to_num")) test_str_to_num(); if (should_test_function("enum")) test_enum_set(); + if (should_test_function("enum")) test_enum_array(); if (should_test_function("highlighting")) test_highlighting(); if (should_test_function("new_parser_ll2")) test_new_parser_ll2(); if (should_test_function("new_parser_fuzzing"))