Date: Thu, 26 Jun 2025 13:02:50 +0200
Hi,
I'm interested in how much appetite there would be for the following set of
functions in <bit>:
template<class T>
T sign_fill(T x) noexcept;// Fills the integer with the most
significant bit of x.
template<class T>
T bit_mask(T x) noexcept;// Returns (T{1} << x) - T{1};
template<class T>
bool get_bit(T x, int i);// Gets ith bit in x.
template<class T>
T set_bit(T x, int i);template<class T>
T set_bit(T x, int i, bool b);// Sets ith bit in x to 1 and b, respectively.
template<class T>
T reset_bit(T x, int i);// Sets ith bit in x to 0.
template<class T>
T flip_bit(T x, int i);// Sets ith bit in x to its complement.
These kinds of things are building blocks used in bit manipulation all the
time.
It's also not trivial to get optimal codegen for all compilers on all
architectures. I've actually overhauled the top answer on the StackOverflow
post at https://stackoverflow.com/q/47981/5740428, and I can say from
experience that not every way to write set_bit(T, int, bool) is equally
good.
Sign-filling is a pretty common technique, and writing it out by hand is
somewhat tedious because it requires going through std::numeric_limits to
do it generically.
Even if we leave these arguments aside, the problem with writing say, (x |
(1 << i)) instead of set_bit(x, i) is the lack of expressiveness. It's
somewhat like writing inline assembly and then puzzling together that cmp
and je collectively perform a jump if two registers are unequal. It's easy
if you did it 1000 times before, but not obvious to novice readers at all.
The question is mainly where to draw the line. There are tons of different
bit manipulation techniques, like isolating the lowest set bit, etc.
However, none of these are anywhere near as common as simple
setting/getting specific bits. I cherry-picked creating bit masks and
sign-filling because they stand out from the crowd, in my experience. Maybe
I could collect some data on this.
Jan
I'm interested in how much appetite there would be for the following set of
functions in <bit>:
template<class T>
T sign_fill(T x) noexcept;// Fills the integer with the most
significant bit of x.
template<class T>
T bit_mask(T x) noexcept;// Returns (T{1} << x) - T{1};
template<class T>
bool get_bit(T x, int i);// Gets ith bit in x.
template<class T>
T set_bit(T x, int i);template<class T>
T set_bit(T x, int i, bool b);// Sets ith bit in x to 1 and b, respectively.
template<class T>
T reset_bit(T x, int i);// Sets ith bit in x to 0.
template<class T>
T flip_bit(T x, int i);// Sets ith bit in x to its complement.
These kinds of things are building blocks used in bit manipulation all the
time.
It's also not trivial to get optimal codegen for all compilers on all
architectures. I've actually overhauled the top answer on the StackOverflow
post at https://stackoverflow.com/q/47981/5740428, and I can say from
experience that not every way to write set_bit(T, int, bool) is equally
good.
Sign-filling is a pretty common technique, and writing it out by hand is
somewhat tedious because it requires going through std::numeric_limits to
do it generically.
Even if we leave these arguments aside, the problem with writing say, (x |
(1 << i)) instead of set_bit(x, i) is the lack of expressiveness. It's
somewhat like writing inline assembly and then puzzling together that cmp
and je collectively perform a jump if two registers are unequal. It's easy
if you did it 1000 times before, but not obvious to novice readers at all.
The question is mainly where to draw the line. There are tons of different
bit manipulation techniques, like isolating the lowest set bit, etc.
However, none of these are anywhere near as common as simple
setting/getting specific bits. I cherry-picked creating bit masks and
sign-filling because they stand out from the crowd, in my experience. Maybe
I could collect some data on this.
Jan
Received on 2025-06-26 11:03:01