I want to apply a bitmask to get only the upper half of bits. So for an uint32 it would be this:
uint32_t version_part = oldID & 0xFFFF0000;
This is all fine when the data type is hardcoded but if this was a templated function and I wanted to provide an arbritary data type (uint8_t, uint16_t, ...) I want to resize the bitmask proportionally (0xF0, 0xFF00, ...) and much preferably at compile time.
Given there is a finite number of data types I suppose you could just make if-cases (static if's?) but I was wondering if there is a nicer way to do it.
Does something like below solve your purpose?
template<typename T>
T maskbits(T oldID)
{
const size_t SZ = sizeof oldID * CHAR_BIT;
const T mask = (static_cast<T>((1ULL << (SZ / 2)) - 1ULL)) << (SZ / 2);
return oldID & mask;
}
The answer of Mohit Jain is a good one. But since you're using templates, you could also do something with template specialisation:
/* general case */
template<typename T> class Mask { };
/* specific cases */
template<> class Mask<uint16_t> {public: static const uint16_t value = 0xFF00; };
template<> class Mask<uint32_t> {public: static const uint32_t value = 0xFFFF0000; };
/* etc. */
template<typename T>
constexpr T maskbits(T uid)
{
return uid & Mask<T>::value;
}
The big plus here is you can leave the general case blank to get a compile error on an unsupported type. Of course you could also make that calculate the mask, that depends on your needs.
Maybe you can try this, it will work for any integer size.
#include <iostream>
template<typename T>
T mask(T a = 0) {
return (~T(0)) << 4*sizeof(T);
}
int main()
{
unsigned char v = mask<unsigned char>();
int v2 = mask(32);
std::cout << "v = 0x" << std::hex << (unsigned int)v << std::endl;
std::cout << "v2 = 0x" << std::hex << (unsigned int)v2 << std::endl;
}
The output is:
v = 0xf0
v2 = 0xffff0000
Edit: I just checked and with optimization enabled the compiler can produce the masks at compile time
User contributions licensed under CC BY-SA 3.0