I am creating wrappers for C structs containing register definitions with heavy use of bitfields. I would like to create reference getters for all of them, to provide consistent shorthand API (real structures may use deep nesting with long names only a HW engineer would love).
For regular values, returning a reference is easy, but for bitfields, I had to create a wrapper similar to std::bitset::reference:
#include <cstdint>
#include <cstdio>
class storage {
public:
auto get_x() { return x_ref{ *this }; }
auto get_y() { return y_ref{ *this }; }
auto& get_z() { return z; }
private:
uint8_t x : 3;
uint8_t y : 5;
uint8_t z;
struct x_ref {
storage& store;
operator uint8_t() { return store.x; }
auto& operator=(uint8_t value) { store.x = value; return *this; }
};
struct y_ref {
storage& store;
operator uint8_t() { return store.y; }
auto& operator=(uint8_t value) { store.y = value; return *this; }
};
};
int main(int argc, char **argv) {
storage s{};
s.get_x() = 3;
s.get_y() = 5;
s.get_z() = 7;
uint8_t x = s.get_x(), y = s.get_y(), z = s.get_z();
std::printf("%u, %u\n", x, y, z);
}
Is there any way to create x/y_ref as a generic template? I would like to be able to write something like auto get_x() { return ref<&storage::x>{ *this }; } which is not a valid syntax for bitfields. std::bitset::reference does not have this problem, since it always stores a reference to uint8_t& (or larger word) and index, so it doesn't have anything to template on.
return ref{ [this]() { return this->x; }, [this](auto value) { this->x = value; } };?s.get_foo()vss.feature_x_static_values.u.version_2137.blah.blah.blah.finally_getting_somewhere.oh_here_it_is.my_foo, just with much more useless Hungarian.