C++11 way to check flags - c++

The typical C-style approach:
#define LOG_ERRORS 1 // 2^0, bit 0
#define LOG_WARNINGS 2 // 2^1, bit 1
#define LOG_NOTICES 4 // 2^2, bit 2
#define LOG_INCOMING 8 // 2^3, bit 3
#define LOG_OUTGOING 16 // 2^4, bit 4
#define LOG_LOOPBACK 32 // and so on...
// Only 6 flags/bits used, so a char is fine
unsigned char flags;
// initialising the flags
flags = LOG_ERRORS;
//initialising to multiple values with OR (|)
flags = LOG_ERRORS | LOG_WARNINGS | LOG_INCOMING;
// sets to 1 + 2 + 8 i.e. bits 0, 1 and 3
// testing for a flag
// AND with the bitmask before testing with ==
if ((flags & LOG_WARNINGS) == LOG_WARNINGS)
...
// testing for multiple flags
// as above, OR the bitmasks
if ((flags & (LOG_INCOMING | LOG_OUTGOING))
== (LOG_INCOMING | LOG_OUTGOING))
...
Is there a better way in C++11, which keeps the old C style interface (LOG_INCOMING | LOG_OUTGOING)? i.e. How can I get rid of the "ugly" way to check which bits are set?
I have been looking at std::bitset but this latter only tests for positional queries (i.e. for example it can test if 3rd bit is set) and cannot test for something like this:
LOG_INCOMING | LOG_OUTGOING

I would replace your macros with static const ints (well, or an enum with explicit values), but other than that your implementation is just fine.
You should not replace good, solid, robust, clear, self-documenting, concise, reliable code with some new template monstrosity just because you can.
Your code is modern enough and this pattern is still very much in use.

I don't see anything wrong with the performance of the code that 0x/1y features will help. If it's already well tested, you probably want to avoid a re-write (especially if existing code depends on it).
If just want some ideas for how you could use features though, there are some different approaches you could take.
constexpr...
constexpr uint8_t bit(const uint8_t n) {
return 1 << n;
}
constexpr static const uint8_t LOG_ERRORS = bit(0);
constexpr static const uint8_t LOG_WARNINGS = bit(1);
if (flags & (LOG_ERROR | LOG_WARNINGS))
binary literals...
static const uint8_t LOG_ERRORS = 0b00000001;
static const uint8_t LOG_WARNINGS = 0b00000010;
if (flags & (LOG_ERRORS | LOG_WARNINGS))
variadic templates...
template<typename T, typename... Ts>
T bit_or(T t, Ts... ts) {
return t | bit_or(ts...);
}
template<typename T>
T bit_or(T t) {
return t;
}
template<typename T, typename... Ts>
bool any_set(T t, Ts... ts) {
return static_cast<bool>(t & (bit_or(ts...)));
}
constexpr uint8_t bit(const uint8_t n) {
return 1 << n;
}
constexpr static const uint8_t LOG_ERRORS = bit(0);
constexpr static const uint8_t LOG_WARNINGS = bit(1);
if (any_set(flags, LOG_ERRORS, LOG_WARNINGS))
My personal preference would be to avoid std::bitset, since it can't be directly evaluated in a boolean context. However, I might consider wrapping flags in a class, and using an enum class : uint8_t for the flags for type safety. The class would probably be something similar to Java's EnumSet. You could easily overload the bitwise operations (&, |, ^, ~, etc...) for it to preserve the C interface.

There is bitset, which, among other things, allows you to set an N bit to true; it also has some methods for conversions to unsigned and to string ( C++ string, not just a null terminated sequence of char C-style )
Other than that, I don't think that there is a more C++-ish way of doing this, but I'll probably keep an approach similar to what Lightness Races in Orbit just described, be conservative and don't add an overhead that you don't need .

Related

Convert last characters of std::array<char, 10> to int

Given the following array: std::array<char, 10> stuff I'd like to convert the last 4 characters to the corresponding int32 value.
I tried to chain OR operations on the last items but doesn't seem to be the right way:
int a = int(stuff[6] | stuff[7] | stuff[8] | stuff[9])
Is there an elegant way to solve this?
What you tried to do has elegance that comes across in not needing an endianness check in order to work properly. What you missed was some shifting to indicate significance in the final value:
int a = stuff[6] << 24 | stuff[7] << 16 | stuff[8] << 8 | stuff[9];
This alone does not care about endianness because from the language's perspective, it is based on values rather than bytes. You determine which values are most significant.
That said, this also assumes an 8-bit byte and at least 4-byte int. If you want elegance of use, you can get it with a safe and general abstraction:
#include <array>
#include <climits>
#include <cstddef>
namespace detail {
// Could be replaced by an inline lambda-template in C++20.
template<typename T, std::size_t N, std::size_t... Is>
constexpr T pack_into_impl(const std::array<std::byte, N>& bytes, std::index_sequence<Is...>) {
// Build final value from right to left to make the math more clear
// and to use the least significant bytes available when N < sizeof(T).
// e.g., bytes[3] << 0 | bytes[2] << 8 | bytes[1] << 16 | bytes[0] << 24
return ((static_cast<int>(bytes[N-Is-1]) << (CHAR_BIT * Is)) | ...);
}
}
// Takes bytes to pack from most significant to least significant.
// N.B. this is not a production-ready doc comment for this function.
template<typename T, std::size_t N>
constexpr T pack_into(std::array<std::byte, N> bytes) {
static_assert(sizeof(T) >= N, "Destination type is too small for this many bytes");
return detail::pack_into_impl<T>(bytes, std::make_index_sequence<N>{});
}
// Convenience overload.
template<typename T, typename... Bytes>
constexpr T pack_into(Bytes... bytes) {
// Check that each Bytes type can be static_cast to std::byte.
// Maybe check that values fit within a byte.
return pack_into<T>(std::array{static_cast<std::byte>(bytes)...});
}
int main() {
static_assert(pack_into<int>(0x12, 0x34, 0x56, 0x78) == 0x12345678);
static_assert(pack_into<int>(0x01, 0x02) == 0x0102);
// pack_into<int>(0x01, 0x02, 0x03, 0x04, 0x05); // static_assert
}
Some of this can be cleaned up in C++20 by using concepts and a []<std::size_t... Is> lambda, but you get the idea. Naturally, you're also free to transform the API to make the size unknown at compile-time for convenience and live with a possible runtime check when too many bytes are given. It depends on your use case.
Believe it or not, even though this is C++, memcpy() is the recommended way to do this kind of thing:
int32_t a;
memcpy(&a, stuff.data() + 6, 4);
It avoids strict aliasing violations, and compilers will optimize the memcpy call away.
Be aware of endianess differences if the data you're loading was created on a different machine with a different CPU architecture.

How should I define a set number of bits in a typedef?

The Problem
I'm currently trying to simulate some firmware in C++11. In the firmware we have a fixed data length of 32 bits, we split this 32 bits into smaller packets e.g we have a packet which as a size of 9 bits, another of 6 which gets packed into the 32 bit word.
In C++ I want to ensure the data I type in is of those lengths. I don't care if I overflow, just that only the 9 bits are operated on or passed onto another function.
Ideally I'd like some simple typedef like:
only_18_bits some_value;
My Attempt
struct sel_vals{
int_fast32_t m_val : 18;
int_fast8_t c_val : 5;
}
But this is a little annoying as I'd have to do this whenever I want to use it:
sel_vals somevals;
somevals.m_val = 5;
Seems a little verbose to me plus I have to declare the struct first.
Also for obvious reasons, I can't just do something like:
typedef sel_vals.m_val sel_vals_m_t;
typedef std::vector<sel_vals_m_t>;
I could use std::bitset<9> but whenever I want to do some maths I have to convert it to unsigned, it just gets a little messy. I want to avoid mess.
Any ideas?
I would suggest a wrapper facade, something along these lines:
#include <cstdint>
template<int nbits> class bits {
uint64_t value;
static const uint64_t mask = (~(uint64_t)0) >> (64-nbits);
public:
bits(uint64_t initValue=0) : value(initValue & mask) {}
bits &operator=(uint64_t newValue)
{
value=newValue & mask;
}
operator uint64_t() const { return value; }
};
//
bits<19> only_19_bits_of_precision;
With a little bit of work, you can define math operator overloads that directly operate on these templates.
With a little bit of more work, you could work this template to pick a smaller internal value, uint32_t, uint16_t, or uint8_t, if the nbits template parameter is small enough.

2 bits size variable

I need to define a struct which has data members of size 2 bits and 6 bits.
Should I use char type for each member?Or ,in order not to waste a memory,can I use something like :2\ :6 notation?
how can I do that?
Can I define a typedef for 2 or 6 bits type?
You can use something like:
typedef struct {
unsigned char SixBits:6;
unsigned char TwoBits:2;
} tEightBits;
and then use:
tEightBits eight;
eight.SixBits = 31;
eight.TwoBits = 3;
But, to be honest, unless you're having to comply with packed data external to your application, or you're in a very memory constrained situation, this sort of memory saving is not usually worth it. You'll find your code is a lot faster if it's not having to pack and unpack data all the time with bitwise and bitshift operations.
Also keep in mind that use of any type other than _Bool, signed int or unsigned int is an issue for the implementation. Specifically, unsigned char may not work everywhere.
It's probably best to use uint8_t for something like this. And yes, use bit fields:
struct tiny_fields
{
uint8_t twobits : 2;
uint8_t sixbits : 6;
}
I don't think you can be sure that the compiler will pack this into a single byte, though. Also, you can't know how the bits are ordered, within the byte(s) that values of the the struct type occupies. It's often better to use explicit masks, if you want more control.
Personally I prefer shift operators and some macros over bit fields, so there's no "magic" left for the compiler. It is usual practice in embedded world.
#define SET_VAL2BIT(_var, _val) ( (_var) | ((_val) & 3) )
#define SET_VAL6BIT(_var, _val) ( (_var) | (((_val) & 63) << 2) )
#define GET_VAL2BIT(_var) ( (_val) & 3)
#define GET_VAL6BIT(_var) ( ((_var) >> 2) & 63 )
static uint8_t my_var;
<...>
SET_VAL2BIT(my_var, 1);
SET_VAL6BIT(my_var, 5);
int a = GET_VAL2BIT(my_var); /* a == 1 */
int b = GET_VAL6BIT(my_var); /* b == 5 */

Reading/Writing Nibbles (without bit fields) in C/C++

Is there an easy way to read/write a nibble in a byte without using bit fields?
I'll always need to read both nibbles, but will need to write each nibble individually.
Thanks!
Use masks :
char byte;
byte = (byte & 0xF0) | (nibble1 & 0xF); // write low quartet
byte = (byte & 0x0F) | ((nibble2 & 0xF) << 4); // write high quartet
You may want to put this inside macros.
The smallest unit you can work with is a single byte. If you want to manage the bits you should use bitwise operators.
Here's a modern answer that takes C++11 into account:
// Fixed-width integer types
#include <cstdint>
// Constexpr construction
constexpr uint8_t makeByte(uint8_t highNibble, uint8_t lowNibble)
{
return (((highNibble & 0xF) << 4) | ((lowNibble & 0xF) << 0));
}
// Constexpr high nibble extraction
constexpr uint8_t getHighNibble(uint8_t byte)
{
return ((byte >> 4) & 0xF);
}
// Constexpr low nibble extraction
constexpr uint8_t getLowNibble(uint8_t byte)
{
return ((byte >> 0) & 0xF);
}
Big benefits:
No nasty union trickery
No ugly macros
No boilerplate
Using standardised fixed-width types
contexpr functions
(I.e. can be used in compile-time calculations and template paramters.)
Just plain simple
(Before anyone asks, the >> 0 and << 0 are for primarily for visual balance, to demonstrate that the same concept is in use even in the exceptional case where no shift is actually needed. If your compiler doesn't optimise those away, complain to your compiler provider, not me.)
However, if your nibbles actually represent something important, e.g. a bitfield, then you might want to create a class/struct.
For example if you were programming a device that required a frame buffer with index 16-colour values, with 2 pixel values packed per byte, you might want to create something like this:
struct PixelPair
{
private:
uint8_t value;
public:
contexpr explicit PixelPair(uint8_t rawValue) :
value { rawValue }
{
}
constexpr PixelPair(uint8_t leftPixel, uint8_t rightPixel) :
value { makeByte(leftPixel, rightPixel) }
{
}
constexpr uint8_t getLeftPixel() const
{
return getHighNibble(this->value);
}
constexpr uint8_t getRightPixel() const
{
return getLowNibble(this->value);
}
constexpr uint8_t getRawValue() const
{
return this->value;
}
};
Note that this is essentially just a vanishingly thin wrapper around the above functions.
In this case it provides:
Type safety - No accidentally mixing up a plain old uint8_t and a specifically designated PixelPair. (See also: Bjarne Stroustrup's 2012 Keynote, where he discusses "Type-rich Programming".)
Improved readability - pixelPair.getLeftPixel() tells you exactly what the code is dealing with: the left-hand pixel of a pair of pixels.
Clear semantics - The code tells you what it is dealing with, not how it is dealing with it. pixelPair.getLeftPixel() tells you that the function is retrieving the left-hand pixel without specifying how, whereas getHighNibble(pixelByte) only tells you the how, i.e. that the high nibble of a pixel byte is being retrieved, it doesn't tell you what that nibble represents - perhaps the high nibble actually represents the right-hand pixel?
You could take this further and create a Pixel class too if you wanted even more type safety, and it could have relevant functions for dealing with the specific pixel format. This sort of code gets you thinking about what kind of data you are dealing with and the relationships between the data, rather than just thinking about the data as quantities of bits and bytes.
You could create yourself a pseudo union for convenience:
union ByteNibbles
{
ByteNibbles(BYTE hiNibble, BYTE loNibble)
{
data = loNibble;
data |= hiNibble << 4;
}
BYTE data;
};
Use it like this:
ByteNibbles byteNibbles(0xA, 0xB);
BYTE data = byteNibbles.data;

C++ binary constant/literal

I'm using a well known template to allow binary constants
template< unsigned long long N >
struct binary
{
enum { value = (N % 10) + 2 * binary< N / 10 > :: value } ;
};
template<>
struct binary< 0 >
{
enum { value = 0 } ;
};
So you can do something like binary<101011011>::value. Unfortunately this has a limit of 20 digits for a unsigned long long.
Does anyone have a better solution?
Does this work if you have a leading zero on your binary value? A leading zero makes the constant octal rather than decimal.
Which leads to a way to squeeze a couple more digits out of this solution - always start your binary constant with a zero! Then replace the 10's in your template with 8's.
The approaches I've always used, though not as elegant as yours:
1/ Just use hex. After a while, you just get to know which hex digits represent which bit patterns.
2/ Use constants and OR or ADD them. For example (may need qualifiers on the bit patterns to make them unsigned or long):
#define b0 0x00000001
#define b1 0x00000002
: : :
#define b31 0x80000000
unsigned long x = b2 | b7
3/ If performance isn't critical and readability is important, you can just do it at runtime with a function such as "x = fromBin("101011011");".
4/ As a sneaky solution, you could write a pre-pre-processor that goes through your *.cppme files and creates the *.cpp ones by replacing all "0b101011011"-type strings with their equivalent "0x15b" strings). I wouldn't do this lightly since there's all sorts of tricky combinations of syntax you may have to worry about. But it would allow you to write your string as you want to without having to worry about the vagaries of the compiler, and you could limit the syntax trickiness by careful coding.
Of course, the next step after that would be patching GCC to recognize "0b" constants but that may be an overkill :-)
C++0x has user-defined literals, which could be used to implement what you're talking about.
Otherwise, I don't know how to improve this template.
template<unsigned int p,unsigned int i> struct BinaryDigit
{
enum { value = p*2+i };
typedef BinaryDigit<value,0> O;
typedef BinaryDigit<value,1> I;
};
struct Bin
{
typedef BinaryDigit<0,0> O;
typedef BinaryDigit<0,1> I;
};
Allowing:
Bin::O::I::I::O::O::value
much more verbose, but no limits (until you hit the size of an unsigned int of course).
You can add more non-type template parameters to "simulate" additional bits:
// Utility metafunction used by top_bit<N>.
template <unsigned long long N1, unsigned long long N2>
struct compare {
enum { value = N1 > N2 ? N1 >> 1 : compare<N1 << 1, N2>::value };
};
// This is hit when N1 grows beyond the size representable
// in an unsigned long long. It's value is never actually used.
template<unsigned long long N2>
struct compare<0, N2> {
enum { value = 42 };
};
// Determine the highest 1-bit in an integer. Returns 0 for N == 0.
template <unsigned long long N>
struct top_bit {
enum { value = compare<1, N>::value };
};
template <unsigned long long N1, unsigned long long N2 = 0>
struct binary {
enum {
value =
(top_bit<binary<N2>::value>::value << 1) * binary<N1>::value +
binary<N2>::value
};
};
template <unsigned long long N1>
struct binary<N1, 0> {
enum { value = (N1 % 10) + 2 * binary<N1 / 10>::value };
};
template <>
struct binary<0> {
enum { value = 0 } ;
};
You can use this as before, e.g.:
binary<1001101>::value
But you can also use the following equivalent forms:
binary<100,1101>::value
binary<1001,101>::value
binary<100110,1>::value
Basically, the extra parameter gives you another 20 bits to play with. You could add even more parameters if necessary.
Because the place value of the second number is used to figure out how far to the left the first number needs to be shifted, the second number must begin with a 1. (This is required anyway, since starting it with a 0 would cause the number to be interpreted as an octal number.)
Technically it is not C nor C++, it is a GCC specific extension, but GCC allows binary constants as seen here:
The following statements are identical:
i = 42;
i = 0x2a;
i = 052;
i = 0b101010;
Hope that helps. Some Intel compilers and I am sure others, implement some of the GNU extensions. Maybe you are lucky.
A simple #define works very well:
#define HEX__(n) 0x##n##LU
#define B8__(x) ((x&0x0000000FLU)?1:0)\
+((x&0x000000F0LU)?2:0)\
+((x&0x00000F00LU)?4:0)\
+((x&0x0000F000LU)?8:0)\
+((x&0x000F0000LU)?16:0)\
+((x&0x00F00000LU)?32:0)\
+((x&0x0F000000LU)?64:0)\
+((x&0xF0000000LU)?128:0)
#define B8(d) ((unsigned char)B8__(HEX__(d)))
#define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) + B8(dlsb))
#define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) + ((unsigned long)B8(db2)<<16) + ((unsigned long)B8(db3)<<8) + B8(dlsb))
B8(011100111)
B16(10011011,10011011)
B32(10011011,10011011,10011011,10011011)
Not my invention, I saw it on a forum a long time ago.