Перенос членов класса C ++ Enum в глобальное пространство имен - PullRequest
0 голосов
/ 27 апреля 2018

Существует ли директива using, которая импортирует элементы enum class непосредственно в глобальное пространство имен модуля компиляции?

У нас есть:

enum Lexeme {....lots of names...};

bool Matches(int lookAhead, Lexeme lxm);

Это рискованно, потому что пользователи часто забывают, что первый аргумент Matches означает «соответствует либо», и пишут:

if (Matches(ADD,SUB)) ...

Компилятор C ++ совершенно счастлив, принимая ADD в качестве целого.

Итак, я попытался сделать Lexeme an enum class:

enum class Lexeme { ...}

Это ловит ошибку. Но теперь моя проблема заключается в том, что весь код, который использует Lexeme константы, должен написать enum class имя:

if (Matches(Lexeme::ADD,Lexeme::SUB)) ...

Существует ли директива using или другая хитрость, чтобы вытянуть все имена Lexeme::* в текущую область? Обратите внимание, что большинство токенов используются в классе (я понимаю, что правильное определение констант является одним из механизмов обеспечения безопасности enum class).

Возможно, лучший план - изменить Matches на MatchesAt или что-то еще, чтобы избежать проблемы? Но я хотел знать правила для C ++ и C ++ XX, по крайней мере.

Что я пробовал:

Это связано, но не относится к необходимым enum class префиксам.

Я тоже пробовал что-то вроде using foo::bar::Lexeme; но увы безрезультатно.

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

На другой ноте, способ избежать записи Lexeme:: каждый раз будет просто создать более короткий псевдоним:

enum class Lexeme { /* lotsa names */ };
using L = Lexeme;

if (Matches(3, L::SUB)) //...

Это хорошо работает, если есть только один или два файла, в которых эти значения широко используются, а другие варианты используются редко. Мне только что пришлось использовать подобное решение, где у меня был класс Parameter, который считывал вещи из XML. У меня есть enum class ElementType { INTEGER, BOOLEAN, /* etc*/ } и инфраструктура для разбора. В файле парсера у меня есть:

using ET = ElementType;

template<ET et>
struct parser;

// Specializations for each ElementType
template<>
struct parser<ET::INTEGER> {
    using type = int;
    int parseSingle(const string& s) // ...
}

Хотя за пределами этого файла у меня есть несколько вариантов использования констант ElementType :: *, и я использую полное имя класса enum. Если это станет слишком обременительным, ничто не помешает мне добавить этот псевдоним в другой файл.

0 голосов
/ 27 апреля 2018

Вы можете сделать класс целочисленных оболочек не конвертируемым во что-либо еще и сделать из него некоторые константы.

struct Lexeme
{
   private: int m_value;

   public: explicit constexpr Lexeme(int value) noexcept
   : m_value{value}
   {}
};

inline constexpr Lexeme const ADD{1};
inline constexpr Lexeme const SUB{2};

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

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