How to avoid macros in instantiating my templated class?

Viewed 89

We use tons of registers, all are struct of bit fields, e.g.

struct MyRegister { 
    uint32_t bit_field0 : 2;
    uint32_t bit_field1 : 5;
...
};
volatile MyRegister my_register; // Mapped by the linker to a specific address.

I want to create a template which helps me create a shadow register. Something like:

Shadow<> my_register_shadow(my_register); // my_register_shadow is a variable initialized with my_register address and value (reads my_register value).
my_register_shadow.bit_field0 = 2; // Doesn't access to real register my_register.
my_register_shadow.bit_field1 = 6; // Doesn't access to real register my_register.
my_register_shadow.flush(); // Only now write to my_register.

My current solution:

template <typename T>
class Shadow : public T
{
public:
    Shadow(volatile T& reg) : T(reg), reg_(reg) {}
    void flush() { reg_ = *this; }
private:
    volatile T& reg_;
};

#define SHADOW_REG(SHADOW, REG) Shadow<decltype(REG)> SHADOW(REG)
SHADOW_REG(my_register, my_register_shadow); // Define my_register_shadow variable.
my_register_shadow.bit_field0 = 2; // Doesn't access to real register my_register.
my_register_shadow.bit_field1 = 6; // Doesn't access to real register my_register.
my_register_shadow.flush(); // Only now write to my_register.

I'm looking for a solution w/o macro, any idea?

1 Answers

A simple templated factory will do what you need:

template <typename T>
Shadow<T> createShadow(T& reg) { return {reg}; }

auto my_register_shadow = createShadow(my_register); // Define my_register_shadow variable.
my_register_shadow.bit_field0 = 2; // Doesn't access to real register my_register.
my_register_shadow.bit_field1 = 6; // Doesn't access to real register my_register.
my_register_shadow.flush(); // Only now write to my_register.

Related