Предположим, что у меня есть такая структура:
struct my_struct
{
int a;
int b;
}
У меня есть функция, которая должна установить новое значение для "a" или "b". Эта функция также требует указать, какую переменную установить. Типичным примером может быть следующее:
void f(int which, my_struct* s, int new_value)
{
if(which == 0)
s->a = new_value;
else
s->b = new_value;
}
По причинам, которые я не буду писать здесь, я не могу передать указатель на a/b на f. Поэтому я не могу вызвать f с адресом my_struct:: a или my_struct:: b. Еще одна вещь, которую я не могу сделать, - объявить вектор (int vars [2]) в my_struct и передать целое число как индекс в f. В основном в f мне нужно получить доступ к переменным по имени.
Проблема с предыдущим примером заключается в том, что в будущем я планирую добавить больше переменных в структуру, и в этом случае я буду помнить о добавлении дополнительных операторов if в f, что плохо для переносимости. То, что я могу сделать, это написать f как макрос, например:
#define FUNC(which)
void f(my_struct* s, int new_value) \
{ \
s->which = new_value; \
}
а затем я могу вызвать FUNC (a) или FUNC (b).
Это будет работать, но я не люблю использовать макросы. Поэтому мой вопрос: есть ли способ достичь той же цели, используя шаблоны вместо макросов?
EDIT. Я попытаюсь объяснить, почему я не могу использовать указатели, и мне нужен доступ к переменной по имени. В основном структура содержит состояние системы. Эти системы должны "отменить" свое состояние по запросу. Undo обрабатывается с помощью интерфейса undo_token следующим образом:
class undo_token
{
public:
void undo(my_struct* s) = 0;
};
Поэтому я не могу передавать указатели на метод отмены из-за полиморфизма (mystruct также содержит переменные других типов).
Когда я добавляю новую переменную в структуру, я обычно добавляю новый класс, например:
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}
};
Проблема в том, что я не знаю указателя на s при создании токена, поэтому я не могу сохранить указатель на s:: a в конструкторе (который бы решил проблему). Класс для "b" тот же, просто мне нужно написать "s- > b" вместо s- > a
Возможно, это проблема дизайна: мне нужен токен отмены для типа переменной, а не один для переменной...