I am trying to use static_assert for registers for a FPGA and defined the following unions of struct with bitfields and all variable. But whenever I try to compile static_assert won't compile and I get an error saying the variable doesn't name a type. If I try to forward declare, it doesn't solve the problem. I'm not sure what the right pattern is to get the static_assert to work. Any ideas of the correct way to write the following code?
so.h:
#include <stdint.h>
#define t_f2bits_addr (0x0000)
typedef union {
struct {
uint32_t do_it : 1;
uint32_t fault : 1;
} field;
uint32_t all;
} t_f2bits_type;
#define t_f2bits_ptr (*(volatile t_f2bits_type *)t_f2bits_addr)
t_f2bits_type myVar;
myVar.field.do_it = 0x1;
myVar.field.fault = 0x1;
static_assert(myVar.all == 0x3, "Not equal");
so.c
#include "so.h"
int main()
{
return 0;
}
run:
g++ so.c
In file included from so.c:1:0:
so.h:15:1: error: ‘myVar’ does not name a type
myVar.field.do_it = 0x1;
^~~~~
so.h:16:1: error: ‘myVar’ does not name a type
myVar.field.fault = 0x1;
^~~~~
so.h:17:1: error: non-constant condition for static assertion
static_assert(myVar.all == 0x3, "Not equal");
^~~~~~~~~~~~~
so.h:17:1: error: the value of ‘myVar’ is not usable in a constant expression
so.h:14:15: note: ‘myVar’ was not declared ‘constexpr’
t_f2bits_type myVar;
^~~~~
In C++20, you might use std::bit_cast
:
struct field {
uint32_t do_it : 1;
uint32_t fault : 1;
};
constexpr field myVar = [](){
field myVar;
myVar.do_it = 0x1;
myVar.fault = 0x1;
return myVar;
}();
static_assert(std::bit_cast<uint32_t>(myVar) == 0x3, "Not equal");
Demo (only msvc has std::bit_cast
there).
Notice that bitfield is really implementation specific (think about endianess), and the static_assert
might pass or not depending of compilers/architecture/...