строго типизированные перечисления не могут быть использованы в качестве аргументов того же базового типа?

Рассмотрим следующий код. Я предполагал, что, указав тип строго типизированного перечисления, я смогу использовать его для передачи функций и шаблонов одного типа, поскольку указанный базовый тип один и тот же; хотя компилятор жалуется, что приведение к типу отсутствует. В приведенном ниже коде удаление ключевого слова class и спецификатор на перечислении Test::TOTAL_ITEMS вернуться к TOTAL_ITEMS буду работать. Я понимаю, что они не хотят никаких преобразований типов для строго типизированных перечислений, но когда базовый тип совпадает с типом, который, как ожидается, будет получен функцией или шаблоном, я ожидаю, что компилятор не будет жаловаться на это и не будет принудительно конкретный актерский состав. Мысли?

#include <iostream>
#include <cstdint>

template <typename T, std::size_t N = 10>
class Y {
public:
Y() : z_() {
}
~Y() = default;

private:
T z_[N];
};

class X {
public:
enum class Test : std::size_t {
ITEM1 = 0,
ITEM2,
TOTAL_ITEMS,
};

private:
Y<int, Test::TOTAL_ITEMS> collection;
};

int main() {
X xx;
}

1

Решение

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

#include <type_traits>
Y<int, static_cast<std::underlying_type<Test>::type>(Test::TOTAL_ITEMS)> collection;

Или, если все, что вас волнует, это указание базового типа для вашего перечисления, тогда отбросьте class ключевое слово из его определения, и ваш код будет скомпилирован как есть.

enum Test : std::size_t {
// ...
};
3

Другие решения

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

Когда вы хотите конвертировать enum class к другому типу, вы должны сделать это эксплицитно:

enum class Foo : int { FEE, FYE, FOE, FUM };
void f(Foo x) {};
void g(int x) {};

int main()
{
f(Foo::FEE);                   // Okay: correct type
//f(0);                        // Error: no implicit conversion
f(static_cast<Foo>(0));        // Okay: explicitly converted
//g(Foo::FYE);                 // Error: no implicit conversion
g(1);                          // Okay: correct type
g(static_cast<int>(Foo::FYE)); // Okay: explicitly converted
}

Живая демо. Увидеть std::underlying_type когда вы хотите программно извлечь тип.

0

По вопросам рекламы [email protected]