Date: Fri, 27 Jun 2025 06:26:37 +0000
I’ve used a version of all of these, semi-regularly.
However, they are so trivial to implement that it has never occurred to me to write a function to do those.
There might be an argument to be made that were you to write these functions yourself you wouldn’t always get the optimal code-gen,
but that is also a reason why it never occurred to me to write these functions, because sometimes the indexes are known constants and sometimes they are not, and what is more “efficient” can just be decided the moment I code those.
It might be easier to sell these by packaging them with a set of bit operations, like a shift out (i.e. left or right shift overflow bits goes into a separate integer), mask multiple bits, bit order swaps, etc…
Ps. They should all be constexpr, noexcept, with unsigned indexes.
From: Std-Proposals <std-proposals-bounces_at_[hidden]> On Behalf Of Jan Schultke via Std-Proposals
Sent: Thursday, June 26, 2025 13:03
To: C++ Proposals <std-proposals_at_[hidden]>
Cc: Jan Schultke <janschultke_at_[hidden]>
Subject: [std-proposals] More C++ bit manipulation utilities
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
However, they are so trivial to implement that it has never occurred to me to write a function to do those.
There might be an argument to be made that were you to write these functions yourself you wouldn’t always get the optimal code-gen,
but that is also a reason why it never occurred to me to write these functions, because sometimes the indexes are known constants and sometimes they are not, and what is more “efficient” can just be decided the moment I code those.
It might be easier to sell these by packaging them with a set of bit operations, like a shift out (i.e. left or right shift overflow bits goes into a separate integer), mask multiple bits, bit order swaps, etc…
Ps. They should all be constexpr, noexcept, with unsigned indexes.
From: Std-Proposals <std-proposals-bounces_at_[hidden]> On Behalf Of Jan Schultke via Std-Proposals
Sent: Thursday, June 26, 2025 13:03
To: C++ Proposals <std-proposals_at_[hidden]>
Cc: Jan Schultke <janschultke_at_[hidden]>
Subject: [std-proposals] More C++ bit manipulation utilities
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
Received on 2025-06-27 06:26:41