Let’s suppose I have a struct like this:
struct my_struct { int a; int b; }
I have a function which should set a new value for either ‘a’ or ‘b’. This function also requires to specify which variable to set. A typical example would be like this:
void f(int which, my_struct* s, int new_value) { if(which == 0) s->a = new_value; else s->b = new_value; }
For reasons I won’t write here I cannot pass the pointer to a/b to f. So I cannot call f with address of my_struct::a or my_struct::b. Another thing I cannot do is to declare a vector (int vars[2]) within my_struct and pass an integer as index to f. Basically in f I need to access the variables by name.
Problem with previous example is that in the future I plan to add more variables to struct and in that case I shall remember to add more if statements to f, which is bad for portability. A thing I could do is write f as a macro, like this:
#define FUNC(which) void f(my_struct* s, int new_value) \ { \ s->which = new_value; \ }
and then I could call FUNC(a) or FUNC(b).
This would work but I don’t like using macros. So my question is: Is there a way to achieve the same goal using templates instead of macros?
EDIT: I’ll try to explain why I cannot use pointers and I need access to variable by name. Basically the structure contains the state of a system. This systems needs to ‘undo’ its state when requested. Undo is handled using an interface called undo_token like this:
class undo_token { public: void undo(my_struct* s) = 0; };
So I cannot pass pointers to the undo method because of polymorphism (mystruct contains variables of other types as well).
When I add a new variable to the structure I generally also add a new class, like this:
class undo_a : public undo_token { int new_value; public: undo_a(int new_value) { this->new_value = new_value; } void undo(my_struct *s) { s->a = new_value} };
Problem is I don’t know pointer to s when I create the token, so I cannot save a pointer to s::a in the constructor (which would have solved the problem). The class for ‘b’ is the same, just I have to write ‘s->b’ instead of s->a
Maybe this is a design problem: I need an undo token per variable type, not one per variable…
1 Answer