Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect whether a struct's member is a bit-field at compile time in C++?

Given a struct S:

struct S {
  bool a : 1;
  bool b : 1;
};

How to determine that S::a and S::b are bit-fields at compile time?

I was trying to come up a macro like IsBitField(S, a) but had hard time to apply SFINAE with offsetof() or addressof() (which are known to be invalid operations per bit-fields).

like image 202
Acer Avatar asked Apr 04 '21 20:04

Acer


People also ask

Is bit field a compiler dependent?

It depends on your platform (underlying HW architecture + designated compiler), but in general - yes, the compiler most likely needs to add bit-wise operations (which typically result in larger code section and/or slower runtime execution).

What are bit fields in C Explain with syntax?

In C, we can specify size (in bits) of structure and union members. The idea is to use memory efficiently when we know that the value of a field or group of fields will never exceed a limit or is within a small range. For example, consider the following declaration of date without the use of bit fields.

How bit fields are stored in memory?

Again, storage of bit fields in memory is done with a byte-by-byte, rather than bit-by-bit, transfer.

Can we have an array of bit fields?

No, you can't. Bit field can only be used with integral type variables.

What is bit field in C with example?

Bit Fields in C. In C, we can specify size (in bits) of structure and union members. The idea is to use memory efficiently when we know that the value of a field or group of fields will never exceed a limit or is withing a small range. For example, consider the following declaration of date without the use of bit fields.

What is the maximum length of a bit field in C?

In C99, the allowable data types for a bit field include qualified and unqualified _Bool, signed int, and unsigned int. The default integer type for a bit field is unsigned. End of C only. Beginning of C++ only. A bit field can be any integral type or enumeration type. End of C++ only. The maximum bit-field length is 64 bits.

How do you declare a bit field inside a structure?

You can declare a bit field inside a structure. data_type defines the type of data which can be integer, signed integer or unsigned integer. member_name defines the name of the bit-field member inside the structure. width is the number of bits required in the bit field.

What are structures unions and bit fields in C language?

Structures, Unions and Bit fields are some of the important aspects of C programming language. While structures are widely used, unions and bit fields are comparatively less used but that does not undermine their importance. In this tutorial we will explain the concept of Structures, Unions and Bit fields in C language using examples.


1 Answers

First, for a SFINAE solution, the ellipsis overload trick (with expression SFINAE) still works, we just need to find a construct that is ill-formed when applied to a bitfield while well-formed when applied on a normal member.

For example, you cannot form a pointer-to-member if the member is a bitfield.

So we could write:

template <typename T>
struct is_bit_field_t {
    template <typename U>
    static constexpr bool helper(...) {
        return true;
    }
    template <typename U>
    static constexpr bool helper(decltype(&U::a) arg) {
        return false;
    }
    static constexpr bool value = helper<T>(nullptr); 
};

This will test whether the public member a of U is of bitfield type. Explanation:

  • If T::a is a bitfield, then the expression decltype(&U::a) would be ill-formed, which would then SFINAE out the second overload.

Live demo: https://godbolt.org/z/TTn8YPKW3


With C++20, this could be done with concepts, utilizing the fact that you cannot take the address of a bitfield.

The core implementation would just look like:

template <typename T>
concept A_IsBitField = !requires (T t) {
     { &t.a };
};

Live demo: https://godbolt.org/z/W3jbosY93

If you hate to define a standalone concept, you could just use the requires expression instead (with the SFINAE method you have no choice but to create that struct)


Of course, the above only works for the member named a. If you would like to use it with other members, then you need to rewrite the SFINAE trait or the concept, replacing a with whatever member you want. You could write a macro to help you generate those constructs if you need a lot of them.

like image 124
ph3rin Avatar answered Oct 22 '22 01:10

ph3rin