Probabilmente sto cercando di ottenere l'impossibile, ma StackExchange mi sorprende sempre, quindi per favore provate a fare questo:È possibile una mappa da stringa a int per il controllo compilato?
Ho bisogno di mappare un nome ad un intero. I nomi (circa 2k) sono unici. Non ci saranno aggiunte o eliminazioni a quell'elenco e i valori non cambieranno durante il runtime.
L'implementazione come variabili const int
mi consente di verificare la durata e il tipo in fase di compilazione. Anche questo è molto chiaro e dettagliato nel codice. Gli errori sono facilmente individuabili.
L'implementazione come std::map<std::string, int>
mi dà un sacco di flessibilità per creare i nomi da cercare con la manipolazione delle stringhe. Posso usare questo per dare stringhe come parametri alle funzioni che possono interrogare l'elenco per più valori aggiungendo pre-/suffissi a quella stringa. Posso anche eseguire il loop su più valori creando una parte numerica del nome della chiave dalla variabile loop.
Ora la mia domanda è: esiste un metodo per combinare entrambi i vantaggi? Il controllo in fase di compilazione mancante (in particolare per l'esistenza della chiave) quasi uccide il secondo metodo per me. (Specialmente come std::map
restituisce in modo invisibile 0
se la chiave non esiste che crea bug difficili da trovare.) Ma le funzionalità di loop e pre/suffisso sono così dannatamente utili.
Preferirei una soluzione che non utilizzi librerie aggiuntive come boost, ma per favore suggeritele comunque dato che potrei essere in grado di ri-implementarle comunque.
Un esempio su quello che faccio con la mappa:
void init(std::map<std::string, int> &labels)
{
labels.insert(std::make_pair("Bob1" , 45));
labels.insert(std::make_pair("Bob2" , 8758));
labels.insert(std::make_pair("Bob3" , 436));
labels.insert(std::make_pair("Alice_first" , 9224));
labels.insert(std::make_pair("Alice_last" , 3510));
}
int main()
{
std::map<std::string, int> labels;
init(labels);
for (int i=1; i<=3; i++)
{
std::stringstream key;
key << "Bob" << i;
doSomething(labels[key.str()]);
}
checkName("Alice");
}
void checkName(std::string name)
{
std::stringstream key1,key2;
key1 << name << "_first";
key2 << name << "_last";
doFirstToLast(labels[key1.str()], labels[key2.str()]);
}
Un altro obiettivo è che il codice mostrato nelle main()
soggiorni di routine come facile e verbose possibile. (Deve essere compreso dai non programmatori.) La funzione init()
verrà generata dal codice da alcuni strumenti. Le funzioni doSomething(int)
sono fisse, ma posso scrivere attorno a esse le funzioni wrapper. Aiutanti come checkName()
possono essere più complicati, ma devono essere facilmente debuggabili.
Sembra che si vuole costruire le stringhe in fase di esecuzione, ma in qualche modo hanno questo controllato a tempo di compilazione? –
Ci sono modi per convertire le enumerazioni nelle loro stringhe appropriate, quindi dovrebbe essere possibile .. Sebbene sia difficile vedere come è il tempo di compilazione se si costruiscono le stringhe in fase di esecuzione –
'std :: map' ha sicuramente la capacità di raccontare se un elemento è stato inserito. Un modo è "inserire". – chris