Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create bitmask based on a pattern as constexpr

I would like to implement a template function which generates bitmasks in compile-time for integral types. These masks should be based on 8-bit patterns where the pattern will be repeated consecutively to fill the integer. The following example does exactly what I want but in run-time:

#include <iostream>
#include <type_traits>
#include <cstring>

template<typename Int>
typename std::enable_if<std::is_integral<Int>::value, Int>::type
make_mask(unsigned char pattern) {
    Int output {};
    std::memset(&output, pattern, sizeof(Int));
    return output;
}

int main() {
    auto mask = make_mask<unsigned long>(0xf0);
    std::cout << "Bitmask: '" << std::hex << mask << "'" << std::endl;
}

The output of the code above is:

Bitmask: 'f0f0f0f0f0f0f0f0'

I know that the optimizer can eliminate the entire function call in the code above, but I'm looking for a constexpr solution with c++14 and optionally with c++11.

like image 998
Akira Avatar asked Jul 20 '17 22:07

Akira


1 Answers

I'm not sure there's a well-defined solution for signed types. For unsigned types, I'd go with:

template<class Int>
constexpr typename std::enable_if</* std::is_integral<Int>::value && */ std::is_unsigned<Int>::value,
Int>::type make_mask(const unsigned char pattern) {
    return ((std::numeric_limits<Int>::max() / std::numeric_limits<unsigned char>::max()) * pattern);
}

This should work provided that std::numeric_limits<Int>::max() is a multiple of std::numeric_limits<unsigned char>::max(); you could add a check for that to the std::enable_if condition and use another solution if that check fails.

like image 77
Joshua Green Avatar answered Sep 21 '22 09:09

Joshua Green