supponiamo Ho uno struct come questo:È possibile utilizzare i modelli per accedere alle variabili struct in base al nome?
struct my_struct
{
int a;
int b;
}
Ho una funzione che dovrebbe impostare un nuovo valore per entrambi "a" o "b". Questa funzione richiede anche di specificare quale variabile impostare. Un tipico esempio sarebbe questo:
void f(int which, my_struct* s, int new_value)
{
if(which == 0)
s->a = new_value;
else
s->b = new_value;
}
Per ragioni che non scriverò qui non posso passare il puntatore a/b per f. Quindi non posso chiamare f con indirizzo my_struct :: a o my_struct :: b. Un'altra cosa che non posso fare è dichiarare un vettore (int vars [2]) all'interno di my_struct e passare un intero come indice a f. Fondamentalmente in f ho bisogno di accedere alle variabili per nome.
Il problema con l'esempio precedente è che in futuro prevedo di aggiungere più variabili a struct e in tal caso ricorderò di aggiungere ulteriori istruzioni if a f, il che è negativo per la portabilità. Una cosa che ho potuto fare è scrivere f come una macro, come questo:
#define FUNC(which)
void f(my_struct* s, int new_value) \
{ \
s->which = new_value; \
}
e poi ho potuto chiamare FUNC (a) o FUNC (b).
Questo funzionerebbe ma non mi piace usare i macro. Quindi la mia domanda è: esiste un modo per raggiungere lo stesso obiettivo utilizzando i modelli anziché le macro?
EDIT: proverò a spiegare perché non posso usare i puntatori e ho bisogno di accedere alla variabile per nome. Fondamentalmente la struttura contiene lo stato di un sistema. Questo sistema deve "annullare" il suo stato quando richiesto. Annulla è gestito tramite un'interfaccia chiamata undo_token come questo:
class undo_token
{
public:
void undo(my_struct* s) = 0;
};
Quindi non posso passare puntatori al metodo di annullamento a causa del polimorfismo (MyStruct contiene variabili di altri tipi pure).
Quando aggiungo una nuova variabile per la struttura Io in genere anche aggiungere una nuova classe, in questo modo:
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}
};
problema è che non so puntatore s quando creo il token, quindi non posso salva un puntatore a s :: a nel costruttore (che avrebbe risolto il problema). La classe per "b" è la stessa, devo solo scrivere "s-> b" invece di s-> a
Forse questo è un problema di progettazione: ho bisogno di un token di annullamento per tipo di variabile, non uno per variabile ...
FUNC (a) - definirà f (s, nuovo_valore). Ma come lo chiamerai allora? –
Sì, mi dispiace che sia stato un errore. Ma spero che tu abbia capito il punto :) – Emiliano
Anche dopo la tua modifica, usando la mia risposta e Mykola Golubyev, puoi ancora parametrizzare la tua classe di annullamento con un puntatore a un membro di dati di classe e legarla alla classe/struct al richiamo del membro tempo. – camh