2013-05-20 8 views
13

Ho finalmente iniziato a leggere su e non riesco a capire perché sono richiesti i tipi di ritorno trailing.Perché è stata necessaria l'aggiunta di trailing-return-types in C++ 11?

mi sono imbattuto nel seguente esempio, che viene utilizzato per evidenziare il problema:

template<class Lhs, class Rhs> 
    decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs) {return lhs + rhs;} 

L'esempio è illegale, perché decltype(lhs+rhs) non funziona, dal momento che gli identificatori lhs e rhs sono valide solo dopo la fase di parsing .

Suppongo che la mia domanda riguardi la tempistica della risoluzione di tipo decltype. Se non sbaglio, la parola chiave decltype viene utilizzata per determinare il tipo di un'espressione in fase di compilazione.

Non riesco a vedere uno svantaggio di avere decltype eseguire la risoluzione del tipo dopo il completamento di tutte le analisi (che funzionerebbe correttamente per l'esempio precedente). Credo che questo sarebbe stato un modo più semplice per risolvere il problema ...

invece, lo standard C++ 11 fornisce trailing-return-tipo:

template<class Lhs, class Rhs> 
    auto adding_func(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs) {return lhs + rhs;} 

Non ho alcun dubbio che mi manca qualcosa, dal momento che non riesco a vedere l'altro uso di tipi di ritorno finali. Dov'è il difetto nel mio ragionamento?

I tipi di trailing-return mi sembrano una soluzione eccessivamente complessa poiché la risoluzione del tipo decltype dopo l'analisi del corpo della funzione completa funzionerebbe altrettanto bene?

risposta

18

Non si vede un aspetto negativo di avere decltype eseguire risoluzione tipo dopo tutto analisi viene completata (che funziona bene per l'esempio precedente).

Lo svantaggio è che non è possibile senza alterare fondamentalmente le basi del modello di analisi e elaborazione C++.

Per fare ciò che suggerisci, il compilatore dovrà vedere la sintassi decltype e fare un'analisi lessicale di base del contenuto della sintassi. Quindi, continua a analizzare più del file sorgente. Ad un certo punto (quando?), Decide di andare, "hey, quella roba che ho guardato prima? Ora farò tutto il lavoro di analisi per loro".

Come regola generale, C++ non supporta l'aspetto in anticipo per la definizione dei simboli. L'ipotesi di base del framework di analisi C++ è che, se il simbolo non viene dichiarato prima di essere utilizzato, si tratta di un errore del compilatore.

Le lezioni possono andare via con lookahead, ma solo rispetto ai loro membri. Questo è in parte perché è abbastanza chiaro quando un'espressione id può riferirsi a una variabile membro (cioè: se non si riferisce a una variabile locale o globale già dichiarata nell'ambito). Questo non è il caso qui, dove non siamo sicuri di cosa si possa riferire esattamente l'espressione-id.

Inoltre, ciò che suggerisci crea ambiguità.Che cosa significa questo:

int lhs; 

template<class Lhs, class Rhs> 
    decltype(lhs+rhs) adding_func(const Lhs &lhs, const Rhs &rhs); 

è la sintassi decltype riferendosi alla variabile globale lhs, o il parametro lhs funzione locale?

Il modo in cui lo facciamo ora, c'è una chiara demarcazione tra questi due:

int lhs; 
float rhs; 

template<class Lhs, class Rhs> 
    decltype(lhs+rhs) adding_func1(const Lhs &lhs, const Rhs &rhs); 
template<class Lhs, class Rhs> 
    auto adding_func2(const Lhs &lhs, const Rhs &rhs) -> decltype(lhs+rhs); 

adding_func1 si riferisce alle variabili globali. adding_func2 si riferisce al parametro funzione.

Quindi è possibile interrompere radicalmente ogni compilatore C++ sulla faccia della Terra. Oppure puoi semplicemente specificare in ritardo il tuo tipo di reso.

Oppure è possibile utilizzare l'approccio C++ 14 e not bother to state it at all.

+0

Grazie per la tua eccellente risposta, ora vedo gli usi. Vorrei poter dare un cookie in più per il riferimento C++ 14! –

+0

Sulla cosa C++ 14: è definitivo che verrà incluso? Sembra un mondo di dolore in termini di documentazione ... – MFH

+0

@MFH: è nel [C++ 14 Community Draft] (http://isocpp.org/blog/2013/05/new-paper-n3690-programming- lingue-c-comitato-progetto). Quindi, escludendo conseguenze impreviste, probabilmente sarà in C++ 14. E sì, potrebbe essere un po 'doloroso per la documentazione. Ma di nuovo, vuol dire che non hai ridondanza senza senso come usare 'decltype' per dedurre il tipo che corrisponde esattamente al codice * nella funzione *. –

4

Beh, un problema ovvio è che ti aprirà ai loop.

typedef decltype(lhs+lhs) foo; 
foo lhs; 
+0

Sì, vedo come sarebbe problematico. Ma questo tipo di cose mi sembrano errori di programmazione chiari e potrebbero essere risolti da errori in fase di compilazione. –

+5

@MarcClaesen: Ma non è un errore "chiaro". Per rilevare questo tipo di errore, il compilatore dovrebbe risolvere il problema di interruzione, che è impossibile. –

+0

Oh mio Dio, non posso credere di averlo perso. Grazie a @MikeSeymour! –

Problemi correlati