Как я должен проверить, является ли значение базового типа перечисляемым значением? - PullRequest
0 голосов
/ 07 ноября 2018

Пусть I - некоторый целочисленный тип. Теперь предположим, что у меня есть enum class my_enum_class : I со значениями, которые не могут быть последовательными. И теперь я получаю некоторое значение I. Как проверить, перечислено ли это значение в my_enum_class?

Ответ на аналогичный вопрос (для языка Си) предполагает, что значения являются смежными, и что можно добавить «фиктивное» значение верхней границы и проверить диапазон от 0 до это значение; это не актуально в моем случае. Есть ли другой способ сделать это?

Ответы [ 3 ]

0 голосов
/ 07 ноября 2018

В настоящее время нет способа сделать это.

Существуют предложения по отражению, которые могут превратить его в и / или , которые позволяют выполнять итерацию (во время компиляции и, следовательно, во время выполнения) во времени перечисленные значения в перечислении. Используя это, проверка будет относительно простой.

Иногда люди делают ручное перечисление, часто используя макросы.

0 голосов
/ 07 ноября 2018

Хотя стандарт пока не позволяет вам выполнять самоанализ, есть небольшой обходной путь, который вы можете использовать, который может быть улучшен с помощью ADL. Предоставлено этот старый ответ .

namespace sparse {
  template<typename E>
  constexpr bool in_(std::underlying_type_t<E> i) { return false; }

  template<typename E, E value, E...values>
  constexpr bool in_(std::underlying_type_t<E> e) {
    return static_cast<E>(e) == value || in_<E, values...>(e);
  }
}

Для использования следующим образом:

enum class my_enum: int { a=3, b=4 };

template<>
constexpr auto sparse::in<my_enum> =
     in_<my_enum, my_enum::a, my_enum::b>;

static_assert(sparse::in<my_enum>(3));
static_assert(sparse::in<my_enum>(4));
static_assert(!sparse::in<my_enum>(5))
0 голосов
/ 07 ноября 2018

Нет встроенного способа сделать это. Все I являются «действительными» значениями my_enum_class, поэтому вы ничего не можете сделать с базовым типом. Что касается проверки I s по списку перечислителей, то без размышления просто невозможно это сделать.

В зависимости от контекста я склонен либо строить статический std::unordered_set (и выполнять поиск в нем), либо иметь функцию, перечисляющую все мои перечислители в switch (и возвращающую false, если входные данные не соответствуют ни одному из них), или просто не беспокойтесь , вместо этого где-то документально подтверждая, что передача не перечислимого значения my_enum_class в мои функции будет считаться обманом и иметь неопределенное поведение.

В конечном итоге все это вытекает из того факта, что перечисления должны перечислять «общие удобно именуемые значения» в более широком диапазоне полностью допустимых состояний, а не тип, состоящий только из полностью ограниченного набора констант. Мы почти все злоупотребляем перечислениями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...