Ottenere un riferimento da un blocco try

7

Usando C ++ mi piacerebbe fare qualcosa sulla falsariga di:

  1. Cerca di ottenere un riferimento a qualcosa, ad esempio in una mappa
  2. Se lancia, ritorna subito
  3. Altrimenti, vai e usa il riferimento

Tuttavia, poiché non possiamo dichiarare un oggetto di riferimento senza inizializzarlo in C ++, non possiamo farlo direttamente.

Ad esempio, se fossi felice di passare per valore, potrei fare:

std::map<char, int> mymap {...};
int x;
try {
    x = m.at('a');
} catch (out_of_range& e) {
    return;
}
// do something with x

Tuttavia, poiché ho bisogno di un riferimento, dovrei fare quanto segue che non verrà compilato.

std::map<char, int> mymap {...};
int& x;
try {
    x = m.at('a');
} catch (out_of_range& e) {
    return;
}
// do something with x

Quindi le opzioni che posso vedere sono (1), utilizzare un puntatore, che vorrei evitare, o (2), utilizzare un metodo di mappa diverso che si traduce in un codice più dettagliato, come ad esempio:

std::map<char, int> mymap {...};
auto x_it = m.find('a');
if (x_it == m.end()) {
    return;
}
int& x = x_it->second;
// do something with x

Sono quelle le uniche opzioni o, c'è un altro modo per farlo in modo ordinato?

    
posta Alex 11.08.2016 - 03:18
fonte

2 risposte

11

Il modo normale è spostare la linea "così qualcosa con x" anche all'interno del blocco try :

std::map<char, int> mymap {...};
try {
    int& x = mymap.at('a');
    // do something with x
} catch (out_of_range& e) {
    return;
}

La cosa bella delle eccezioni è che quando viene lanciata un'eccezione, tutto il codice tra le posizioni di lancio e di cattura viene completamente ignorato.
Ciò significa che puoi scrivere il codice all'interno del blocco try { ... } catch con la consapevolezza che tutto ha funzionato bene se raggiungi quella linea.

    
risposta data 11.08.2016 - 08:52
fonte
1

Se avessi voluto restituire un riferimento da entrambi il try e il catch branch, sarebbe facile:

std::map<char, int> mymap {...};
int &x = [&]() -> int & { try {
    return mymap.at('a');
} catch (std::out_of_range& e) {
    return some_default_value;
} } ();
// do something with x

Ma nel tuo caso, solo il ramo try restituisce un riferimento, quindi il tipo di ritorno dell'intero blocco try non è un int & ma più simile a optional<int &> . Il problema è che C ++ 17 non è ancora uscito.

Tuttavia, optional<int &> è isomorfo a int * , quindi in definitiva l'uso di un puntatore qui sembra la cosa giusta da fare. Se non ti piace la sintassi -> , puoi semplicemente riassegnare int &y = *x; .

    
risposta data 12.08.2016 - 18:50
fonte

Leggi altre domande sui tag