2015-09-08 22 views
15

Sto leggendo this question on isocpp FAQ here, questa domanda sta spiegando come scrivere il tipo di ritorno per ???Che cosa significa questa sintassi "decltype (* (T *) (0) ** (U *) (0))" significa?

template<class T, class U> 
??? mul(T x, U y) 
{ 
return x*y; 
} 

ho capito il modo più semplice è quello di scrivere auto mul(T x, U y) -> decltype(x*y), tuttavia la domanda dà anche un altro modo, che è quello di sostituire ??? da decltype(*(T*)(0)**(U*)(0)). Ma non capisco perfettamente cosa stia realmente facendo questo decltype(*(T*)(0)**(U*)(0)), sembra che stia dichiarando un puntatore temporaneo T* e inizializzarlo a zero e quindi dereferenziare il puntatore, quindi moltiplicato per la stessa controparte per il tipo U, la mia comprensione è giusta?

Ma perché utilizzare i puntatori? Penso che anche decltype(T(0)*U(0)) o decltype(T{0}*U{0}) dovrebbero funzionare. spaccatura

+2

Ciò presuppone che 'T 'e' U' hanno un costruttore che prende un singolo parametro intero. Il modo puntatore non fa supposizioni sui costruttori di 'T' e' U'. –

+4

Nota, non è un comportamento indefinito poiché è [in un contesto non valutato] (http://stackoverflow.com/a/28723577/1708801) –

risposta

20
decltype(*(T*)(0)**(U*)(0)) 

Ammettiamolo up:

(T*)(0) //cast a null pointer to a T* 
*(T*)(0) //dereference, giving a T 

(U*)(0) //cast a null pointer to a U* 
*(U*)(0) //dereference, giving a U 

(*(T*)(0)) * (*(U*)(0)) //the result of multiplying a U and a T 

decltype(T(0)*U(0)) è equivalente solo se T e U avere costruttori che assumono una singola int (o qualcosa che può essere convertito in modo implicito da un intero letterale).

La libreria standard ha già un std::declval per fare questo in modo più pulito:

decltype(std::declval<T>() * std::declval<U>()) 
0

questo infatti soggetto a errori.

nella soluzione, in pratica si presuppone che il costruttore possa ottenere 0 come argomento e che potrebbe non essere il caso.

frammento sostanzialmente gettato NULL certa puntatore T oggetto, quindi estrarre T con l'operatore *, ora abbiamo lasciato con praticamente decltype({T object}*{U object}) assume che in fase di compilazione, il decltype sarà sostituito dal tipo reale e in tempo di esecuzione non ci saranno puntatori. ma questo codice è molto brutto e non mantenibile.

una soluzione migliore è quello di utilizzare C++ 11 std::result_of:
typename std::result_of<declval<T>()*declval<U>()>::type

declval fa qualcosa di simile a *(T*)(0) solo restituisce r-valore di riferimento (che significa T&&)

+4

Questo non è ciò che 'result_of' è per, e non sarebbe compilato qui. – Barry

Problemi correlati