Поскольку стандарт C ++ не упоминает о математической библиотеке constexpr
, решение:
constexpr uint64_t bits(const uint64_t x) {
int i = 64;
uint64_t mask = 0x8000000000000000;
while (i > 0) {
if ((mask & x) != 0) return i;
i--;
mask /= 2; // do not use >>, which is a non-constexpr in standard.
}
return 1;
}
, тогда пример кода будет выглядеть так:
struct Bar {
bool b: 1;
Foo foo : bits(static_cast<int>(Foo::FEnd) - 1);
};
Если выиспользуя GCC, есть встроенный constexpr log2 (x), тогда код будет:
struct Bar {
bool b: 1;
Foo foo : (int)std::log2(static_cast<int>(Foo::FEnd) - 1) + 1;
};
Edit : реализация версии GCC std::log2(x)
:
template<typename _Tp>
constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
double>::__type
log2(_Tp __x)
{ return __builtin_log2(__x); }
Edit2 : как уже упоминалось @uneven_mark, std::log2(x)
возвращает double
и может привести к ошибкам в зависимости от ввода, поэтому рекомендуется использовать пользовательские функции constexpr
с проверками даже с использованием GCC.