Можно ли определить мощность c ++ enum class
:
enum class Example { A, B, C, D, E };
Я пытался использовать sizeof
однако он возвращает размер элемента enum.
sizeof(Example); // Returns 4 (on my architecture)
Есть ли стандартный способ получить мощность (5 в моем примере)?
Не напрямую, но вы могли бы использовать следующий прием:
enum class Example { A, B, C, D, E, Count };
Тогда мощность доступна как (int)Example::Count
,
Конечно, это работает хорошо, только если вы позволяете автоматически присваивать значения перечисления, начиная с 0. Если это не так, вы можете вручную назначить правильное количество элементов для Count, что на самом деле не отличается от необходимости поддерживать отдельную константу тем не мение:
enum class Example { A = 1, B = 2, C = 4, D = 8, E = 16, Count = 5 };
Недостатком является то, что компилятор позволит вам использовать Example::Count
в качестве аргумента для значения перечисления — так что будьте осторожны, если вы используете это! (Лично я считаю, что на практике это не является проблемой.)
constexpr auto TEST_START_LINE = __LINE__;
enum class TEST { // Subtract extra lines from TEST_SIZE if an entry takes more than one
ONE = 7
, TWO = 6
, THREE = 9
};
constexpr auto TEST_SIZE = __LINE__ - TEST_START_LINE - 3;
Это происходит от UglyCoder’s answer но улучшает это тремя способами.
BEGIN
а также SIZE
) (Ответ Кэмерон также есть эта проблема.)
Сохраняет UglyCoder-х преимущество перед Ответ Кэмерон что перечислителям могут быть присвоены произвольные значения.
Проблема (поделился с UglyCoder но не с Cameron) делает новые строки и комментарии значимыми … что неожиданно. Таким образом, кто-то может добавить запись с пробелами или комментарий без настройки TEST_SIZE
расчет.
enum class TEST
{
BEGIN = __LINE__
, ONE
, TWO
, NUMBER = __LINE__ - BEGIN - 1
};
auto const TEST_SIZE = TEST::NUMBER;
// or this might be better
constexpr int COUNTER(int val, int )
{
return val;
}
constexpr int E_START{__COUNTER__};
enum class E
{
ONE = COUNTER(90, __COUNTER__) , TWO = COUNTER(1990, __COUNTER__)
};
template<typename T>
constexpr T E_SIZE = __COUNTER__ - E_START - 1;
Один из приемов, который вы можете попробовать, — это добавить значение enum в конец списка и использовать его в качестве размера. В вашем примере
enum class Example { A, B, C, D, E, ExampleCount };
Существует один трюк, основанный на X () — макросах: image, у вас есть следующее перечисление:
enum MyEnum {BOX, RECT};
Переформатируйте это, чтобы:
#define MyEnumDef \
X(BOX), \
X(RECT)
Затем следующий код определяет тип перечисления:
enum MyEnum
{
#define X(val) val
MyEnumDef
#undef X
};
А следующий код вычисляет количество элементов enum:
template <typename ... T> void null(T...) {}
template <typename ... T>
constexpr size_t countLength(T ... args)
{
null(args...); //kill warnings
return sizeof...(args);
}
constexpr size_t enumLength()
{
#define XValue(val) #val
return countLength(MyEnumDef);
#undef XValue
}
...
std::array<int, enumLength()> some_arr; //enumLength() is compile-time
std::cout << enumLength() << std::endl; //result is: 2
...
Нет, вы должны написать это в коде.
Вы также можете рассмотреть static_cast<int>(Example::E) + 1
который устраняет лишний элемент.