I have a piece of code that returns the value of some bits of a given number (I counted enum classes as a number too, using a static_cast).
template<typename Type>
bool get_bits(Type input, uint8_t offset, uint8_t n, Type* destination)
{
if (offset + n> sizeof(Type) * 8)
return false;
Type bitmask = 0;
for (int i = 0; i < n; ++i)
bitmask |= (1 << i);
*destination = static_cast<Type>(input >> offset & bitmask);
return true;
}
This function tries to return the value of n
bits of input
beginning from the offset
. It works fine for integral types but when I try to use it with enum classes, compilation fails. I tried to use std::underlying_type and then it worked for enum classes but not for integral types :|. How can I use it for both of them? I mean if the type is enum class, I want to cast the input to its underlying_type
, do some bitwise operations, and then store the result (using static_cast
) to the destination. But these casts should not be done for integral types that don't have underlying_type.
If you need it often, it's possible to write an adapter over std::underlying_type
. Something like this
namespace detail {
template<typename T, bool = std::is_enum<T>::value>
struct underlying_type { using type = T; };
template<typename T>
struct underlying_type<T, true> : ::std::underlying_type<T> {};
}
When you use detail::underlying_type<T>
substitution occurs into the default argument too. When the supplied type is not an enumeration, the primary template matches the arguments (implicitly), and the exposed type
is T
.
When the supplied type is an enumeration (and only then), the specialization gets used. And all it does is forward to the standard trait.