On the Bit Twiddling Hacks website the following algorithm is provided to round up an integer to the next power of two:
unsigned int v; // compute the next highest power of 2 of 32-bit v
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
I would like to code a metaprogramming function that will compute the same operation:
and here is the form of the expected function:
template <typename Type,
// Something here (like a recursion index)
class = typename std::enable_if<std::is_integral<Type>::value>::type,
class = typename std::enable_if<std::is_unsigned<Type>::value>::type>
constexpr Type function(const Type value)
{
// Something here
}
How to do that ?
Example: for value = 42
it should return 64
This ought to implement the algorithm you give:
template<typename T>
constexpr T roundup_helper( T value, unsigned maxb, unsigned curb ) {
return maxb<=curb
? value
: roundup_helper( ((value-1) | ((value-1)>>curb))+1, maxb, curb << 1 )
;
}
template<typename T,
typename = typename enable_if<is_integral<T>::value>::type,
typename = typename enable_if<is_unsigned<T>::value>::type>
constexpr T roundup( T value ) {
return roundup_helper( value, sizeof(T)*CHAR_BIT, 1 );
}
At least, it seems to work fine in my test program.
Alternatively, you can move the v-1
and v+1
out of the helper function like so:
template<typename T>
constexpr T roundup_helper( T value, unsigned maxb, unsigned curb ) {
return maxb<=curb
? value
: roundup_helper( value | (value>>curb), maxb, curb << 1 )
;
}
template<typename T,
typename = typename enable_if<is_integral<T>::value>::type,
typename = typename enable_if<is_unsigned<T>::value>::type>
constexpr T roundup( T value ) {
return roundup_helper( value-1, sizeof(T)*CHAR_BIT, 1 )+1;
}
Another possibility is to take advantage of default arguments and put it all in a single function:
template<typename T,
typename = typename enable_if<is_integral<T>::value>::type,
typename = typename enable_if<is_unsigned<T>::value>::type>
constexpr T roundup(
T value,
unsigned maxb = sizeof(T)*CHAR_BIT,
unsigned curb = 1
) {
return maxb<=curb
? value
: roundup( ((value-1) | ((value-1)>>curb))+1, maxb, curb << 1 )
;
}