It seems that _BitScanReverse, despite being an intrinsic and not a real function, can't be called in a constexpr function in Visual C++. I'm aware that I can implement this operation myself in a much slower way, which would be fine for the case where it's evaluated at compile-time but it's unfortunate that it wouldn't just be the 1-clock-cycle, single CPU instruction (BSR) for the case where it's evaluated at run-time. I haven't tried __builtin_clz in GCC/Clang yet, but it might or might not have the same sort of issue, and I want this code to work across the major compilers, (with a slow fallback for non-GCC, non-Clang, non-VC compilers).
Ideas/Questions:
Is there an easy way to have a function use one block of code when evaluating at compile-time, so that it can be constexpr-safe, and a different block of code for run-time, so that it can be fast? (If so, this would also be relevant to a few other questions I have.)
Alternatively, is there a way to trick the compiler into being able to evaluate _BitScanReverse for constexpr code?
Side question:
Is there any word of plans to eventually add this to the C++ standard? They've added std::log2 and std::ilogb, but those both go through floating-point numbers, instead of just doing one BSR, (or CLZ and a subtraction on ARM chips).
For C++20
you can use std::bit_width
and others form <bit>
header
template< class T >
constexpr T bit_width(T x) noexcept;
#include <bit>
#include <bitset>
#include <iostream>
#include <array>
using BitArray = std::array<unsigned, 8>;
constexpr BitArray Bits() {
BitArray bits;
for (unsigned x{0}; x != 8; ++x)
bits[x] = std::bit_width(x);
return bits;
}
auto main() -> int {
constexpr BitArray bits = Bits();
for (unsigned x{0}; x != 8; ++x) {
std::cout
<< "bit_width( "
<< std::bitset<4>{x} << " ) = "
<< bits[x] << " "
<< std::bit_width(x) << '\n';
}
}
Try it on Godbolt
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With