2016-07-14 88 views
16

Quindi sono perplesso su come funziona. Dato:Non dovrebbe decltype Trigger Compilation del suo argomento?

template <typename T> 
int foo(T t) { t.foo(); } 

sembra che questa chiamata dovesse fallire:

decltype(foo(int{ 13 })) fail = 42; 

cout << fail << endl; 

Invece it just prints:

Funziona in questo modo su tutti i compilatori che ho accesso a. È corretto questo comportamento? Richiedo un preventivo dallo standard C++.

+0

'std :: type_info :: name()' non è garantito per fornire nulla di affidabile. Dà qualcos'altro in altri casi? – StoryTeller

+0

@StoryTeller Ho eliminato il 'tipo_info' dalla domanda. Speriamo che questo aiuti a chiarire il problema. Questa è una domanda su 'decltype' e su cosa sta richiedendo, stavo solo cercando di usare' type_info' per dimostrare la domanda. –

+5

'decltype' non ha realmente bisogno della definizione completa della funzione per conoscere il tipo risultante. ([Vedere] (http://ideone.com/eHSQ92)). Quindi non c'è motivo di compilare nient'altro che il prototipo. Ma non ho una citazione standard. – StoryTeller

risposta

17

In [dcl.spec]:

Per un'espressione e, del tipo indicato con decltype (e) è definito come segue:

se e è un unparenthesized id-espressione nominare un Ivalue o riferimento introdotto dall'elenco identificativo di una dichiarazione di decomposizione , decltype (e) è il tipo di riferimento indicato nella specifica della dichiarazione di scomposizione ([dcl.decomp]);

in caso contrario, se e è un'espressione id non definita o un accesso di un membro di classe non parificato ([expr.ref]), decltype (e) è il tipo dell'entità denominata da e. Se non esiste tale entità, o se e nomina un insieme di funzioni sovraccariche, il programma è mal formato;

altrimenti, se e è un xvalue, decltype (e) è T & &, dove T è il tipo di e;

altrimenti, se e è un lvalue, decltype (e) è T &, dove T è il tipo di e;

altrimenti, decltype (e) è il tipo di e.

L'operando dello specificatore decltype è un operando non valutata (Clausola [expr]).

(enfasi mia)

Così il vostro foo(int{ 13 }) non viene mai valutata.

+0

Risposta perfetta, grazie. Avevo paura di accettare [la risposta di Jesper Juhl "perché ho detto così"] (http://stackoverflow.com/a/38373961/2642059). –

+0

Mi chiedo se questo implichi realmente che la compilazione debba avere successo. Per esempio. in '1? 0: foo (int {13}) 'la chiamata non viene mai valutata, ma non mi aspetto che questo venga compilato. (Probabilmente ci sono alcune regole specifiche su cosa si fa esattamente nel tipo di controllo degli operandi non valutati ...?) – chi

+4

Se si modifica la definizione del modello di funzione sopra a 'modello auto foo (T t) {t.foo(); } ', tuttavia sembra che l'istanziazione del modello avvenga - il che per me ha senso, dato che senza la deduzione del tipo restituito, non c'è modo per' decltype' di produrre qualcosa. Questo, naturalmente, termina con un errore in fase di compilazione. Dove si trova questo comportamento nella clausola precedente? Mi sto perdendo qualcosa? – thokra

5

Le espressioni in decltype sono definite dallo standard per non essere valutate, vengono solo analizzate per ottenere il tipo di espressione.

+5

Domanda obbligatoria per fare riferimento al documento master dell'universo. –

+6

Questa è una risposta breve. Ho intenzione di fare un commento su di esso che è più lungo della risposta stessa: ho già stabilito che i compilatori che ho accesso possano supportare la tua affermazione. Quindi la domanda è: "Questo comportamento è corretto?" Per stabilire che dovrai fare riferimento a qualcosa di più della tua conoscenza acquisita. –

+0

@ JonathanMee di che uso è per te? Ti viene detto che i compilatori sono corretti, perché hai bisogno di un riferimento alle specifiche? Hai intenzione di verificare la sua risposta in base al testo della specifica? Quanto sei sicuro di non essere ingannato dalla risposta nel credere che le specifiche lo dicono, a prescindere da ciò che le specifiche effettivamente dicono? –