How to write a constexpr function to swap endianess of an integer, without relying on compiler extensions and can you give an example on how to do it?
Yes, it's pretty easy; here's a recursive (C++11-compatible) implementation (unsigned integral types only):
#include
#include
#include
template
constexpr typename std::enable_if::value, T>::type
bswap(T i, T j = 0u, std::size_t n = 0u) {
return n == sizeof(T) ? j :
bswap(i >> CHAR_BIT, (j << CHAR_BIT) | (i & (T)(unsigned char)(-1)), n + 1);
}
Example.
Here I'm using j as the accumulator and n as the loop counter (indexing bytes).
If you have a compiler supporting C++17 fold expressions, it's possible to write something that expands out into exactly what you'd write by hand:
template
constexpr T bswap_impl(T i, std::index_sequence) {
return ((((i >> (N * CHAR_BIT)) & (T)(unsigned char)(-1)) <<
((sizeof(T) - 1 - N) * CHAR_BIT)) | ...);
}; // ^~~~~ fold expression
template::type>
constexpr U bswap(T i) {
return bswap_impl(i, std::make_index_sequence{});
}
The advantage of this form is that because it doesn't use loops or recursion, you're pretty much guaranteed to get optimal assembly output - on x86-64, clang even manages to work out to use the bswap instruction.