Почему я должен явно приводить перечисление, для которого я указал базовый тип? - PullRequest
3 голосов
/ 20 мая 2019

Недавно я узнал, что могу указать базовый тип перечислителя в C ++ 11.

Я заметил, что, например, я не могу использовать перечислитель с базовым типом uint16_tв качестве аргумента для параметра uint16_t.См. Следующий пример:

#include <stdint.h>

enum class Apples : uint16_t
{
    GRANNY_SMITH = 1
};

class AppleWatcher
{
    uint16_t m_apple;
public:
    AppleWatcher(const uint16_t apple) : m_apple(apple) {};

};

int main()
{
    AppleWatcher(static_cast<uint16_t>(Apples::GRANNY_SMITH));  // This works

    AppleWatcher(Apples::GRANNY_SMITH); // Compiler error here

    return 0;
}

Мне все еще приходится явно приводить к базовому типу, чтобы использовать его в таких случаях, так какова цель этой функции?

Ответы [ 2 ]

2 голосов
/ 20 мая 2019

Это функция безопасности типа. Неявные преобразования имеют долгую историю связанных с этим проблем в C ++. Взгляните на книгу Стивена Дьюхерста "C ++ Gotchas" - самая длинная глава посвящена преобразованиям.

Напомним, что перечисление - это не что иное, как способ связать постоянное значение с понятным именем. Таким образом, существует ограниченный, документированный набор возможных значений, и путем неявного преобразования вы значительно расширяете домен без какого-либо уведомления. Пример:

void f(uint16_t arg); // arg can have 65536 different values

enum class Apples  : uint16_t { GRANNY_SMITH = 1 }; // one possible value

Если это скомпилировано:

f(Apples::GRANNY_SMITH);

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

f(static_cast<uint16_t>(Apples::GRANNY_SMITH));

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

0 голосов
/ 20 мая 2019

Согласно этой странице документации:

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

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

AppleWatcher(static_cast<uint16_t>(Apples::GRANNY_SMITH));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...