I'm always trying to reduce code verbosity and this question is about that. I think I need a standards expert to explain why my attempt doesn't work, I've done my best to figure it out but have failed.
The goal is to better compose unions. In standards documents such as USB-C PD controller specifications the registers are set out in distinct 8 bit sections.
Universal Serial Bus Type-C TM Port Controller Interface Specification
When coding to meet the above standard I prefer to set out data in an identical fashion and then put abstractions on top of the standard.
For example, there is a register called ALERT_H and ALERT_L, these I represent as two single byte bitfield structures (a common practice in embedded).
When creating a simplifying abstraction I want to combine the two structures into an equivalent structure with a union so that I can check if any bits at all are set in a single if statement (if (Flags) sort of thing).
An Example:
#include <cstdint>
struct ALERT_L
{
uint8_t CC_STATUS : 1;
uint8_t POWER_STATUS : 1;
uint8_t RX_SOP_MSG_STATUS : 1;
uint8_t RX_HARD_RESET : 1;
uint8_t TX_FAIL : 1;
uint8_t TX_DISCARD : 1;
uint8_t TX_SUCCESS : 1;
uint8_t const ALARM_VBUS_VOLTAGE_H : 1;
};
struct ALERT_H
{
uint8_t const ALARM_VBUS_VOLTAGE_L : 1;
uint8_t FAULT : 1;
uint8_t RXBUF_OVFLOW : 1;
uint8_t const VBUS_SINK_DISCNT : 1;
uint8_t Reserved4_7 : 1;
};
/**
* Helper to group the alert bits into a single struct
*/
union ALERT
{
struct : ALERT_H, ALERT_L
{
};
uint16_t Value;
};
static_assert(sizeof(ALERT) == sizeof(uint16_t));
static_assert(sizeof(ALERT) == sizeof(ALERT_H) + sizeof(ALERT_L));
While the above code does compile, I cannot access the anonymous structs CC_STATUS bit or any others, I don't understand why, am I doing something wrong? Is there a way that I can expose that data member without coding getters and setters.
I can achieve this using standard composition but that results in more verbose code which is more verbose than dealing with the 8 bit structs as they are. There are also cases in other standards that do a similar thing but have 4 bytes, which further incentives the interface implication.
I want to achieve this with the anonymous struct or something similar because then the abstraction is transparent and reduces verbosity of use.
alert.regs.CC_STATUS
is more verbose than:
alert.CC_STATUS
This might be impossible in C/C++ but I've thought things were impossible before and been wrong plenty of times.