Есть ли способ указать значение класса enum без необходимости каждый раз печатать его область видимости? - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть некоторые функции, которые могут возвращать либо успех, либо один из фиксированного набора кодов ошибок.Чтобы идентифицировать коды ошибок, у меня было (что-то вроде) это перечисление старой школы в стиле C, объявленное:

enum {
   RESULT_ERROR_BAD_PARAMETER = -3,
   RESULT_ERROR_FILE_NOT_FOUND = -2,
   RESULT_ERROR_GENERAL = -1,
   RESULT_SUCCESS = 0
};
typedef int my_status_t;

my_status_t MyFunc();   // returns a RESULT_* value

Это работало довольно хорошо;шаблон вызова будет выглядеть примерно так:

if (MyFunc() != RESULT_SUCCESS) printf("Error!\n");

... однако было неудобно разрешать неявное преобразование значений my_status_t в int / bool / и т. д., допуская такие неосторожные ошибки:

// Compiles but does the wrong thing at run-time -- bad!
if (MyFunc() == false) printf("Error!\n");

... поэтому в моей новой редакции кода я преобразовал его в enum class вместо:

enum class my_status_t {
   RESULT_ERROR_BAD_PARAMETER = -3,
   RESULT_ERROR_FILE_NOT_FOUND = -2,
   RESULT_ERROR_GENERAL = -1,
   RESULT_SUCCESS = 0
};

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

Единственное, что меня беспокоит, - это то, что новый синтаксис утомителен: теперь я должен написатьчто-то вроде:

if (MyFunc() != my_status_t::RESULT_SUCCESS) printf("Error!\n");

... на каждом сайте вызова - необходимость набирать my_status_t:: каждый раз утомительна и делает код труднее для чтения, без особого увеличения значения (так как RESULT_SUCCESSв любом случае достаточно уникален для моих целей)

Мой вопрос: есть ли какая-то директива стиля using namespace my_status_t;, которую я мог бы использовать, чтобы сказать компилятору экспортировать значения enum из их * 1025?* namespace, чтобы я мог ссылаться на них без необходимости постоянно вводить префикс my_status_t::?

Ответы [ 3 ]

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

Вот способ:

enum class my_status_t { };

inline constexpr my_status_t RESULT_ERROR_BAD_PARAMETER = my_status_t(-3);
// add other enum values here

К сожалению, таким образом вы потеряете некоторые хорошие свойства enum.Подобно тому, как компилятор может предупредить вас, если вы не обрабатываете значение в переключателе (и не забудьте установить базовый тип enum class, если у вас большие значения).

Так что я на самом деле неЯ не рекомендую этот способ (мне больше нравится решение Якка), но, возможно, этот ответ может вам в любом случае помочь ...

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

Если вы собираетесь вводить гораздо больше префиксов области действия помех, чем констант в enum class, то, возможно, стоит потратить время на такой путь:

enum class result {
   ERROR_BAD_PARAMETER = -3,
   ERROR_FILE_NOT_FOUND = -2,
   ERROR_GENERAL = -1,
   SUCCESS = 0
};

constexpr result RESULT_ERROR_BAD_PARAMETER = result::ERROR_BAD_PARAMETER;
constexpr result RESULT_FILE_NOT_FOUND = result::ERROR_FILE_NOT_FOUND;
constexpr result RESULT_ERROR_GENERAL = result::ERROR_GENERAL;
constexpr result RESULT_SUCCESS = result::SUCCESS;

result foo() {
    return RESULT_SUCCESS;
}

int main()
{
    switch (foo())
    {
        case RESULT_SUCCESS:
            ;
    }
    // ^ warning: enumeration value ‘...’ not handled in ...

    if (foo() == RESULT_SUCCESS) {
        return 0;
    }

    /* error: no match for ‘operator==’
    if (foo() == false) {
        return -1;
    }
    */
}

(g ++ -Wall -Wextra -pedantic -std = c ++ 11)

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

Сделайте это изменение:

enum class result {
  ERROR_BAD_PARAMETER = -3,
  ERROR_FILE_NOT_FOUND = -2,
  ERROR_GENERAL = -1,
  SUCCESS = 0
};

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

Теперь ваш код становится:

if (MyFunc() != result::SUCCESS) printf("Error!\n");

, что на целых 1 символ длиннее, чем раньше.

Вы также можете

using my_status_t = result;

, если вы привязаны к my_status_t в качестве имени типа.


Начиная с C ++ 17, нет способа полностью избежать префикса result::.В более поздних версиях C ++ идет речь о using ERROR_BAD_PARAMETER = result::ERROR_BAD_PARAMETER; или о чем-то подобном, но я не знаю, попадут ли они в .

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