Questo non ha nulla a che fare con i modelli, si ottiene lo stesso risultato se T
è solo un typedef per std::string&
piuttosto che un parametro di modello dedotto:
#include <string>
typedef std::string& T;
T Foo(int & i)
{
return T(i);
}
int main()
{
int a = 1;
std::string & s = Foo(a);
}
risposta di Dietmar mi ha fatto capire questa può essere ulteriormente semplificato per:
#include <string>
typedef std::string& T;
int main()
{
int a = 1;
std::string & s = T(a);
}
dove T(a)
è lo stesso come il cast (T)a
cioè (std::string&)a
che (secondo le regole di 5,4 [expr.cast]) farà un const_cast
se è valido (che non è) o un static_cast
se è valido (che non è) o un static_cast
seguita da un const_cast
se è valido (che non è) o un reinterpret_cast
se è valido (quale è) o un reinterpret_cast
seguita da un const_cast
se è valido, altrimenti la l'espressione è mal formata.
Quindi, come ha detto Dietmar, è lo stesso di fare un reinterpret_cast
, cioè
std::string & s = reinterpret_cast<std::string&>(a);
Trovo abbastanza sorprendente che il codice originale compila, ma in quanto è la stessa di quella linea di cui sopra, è consentito per la compilazione . Tuttavia, usare il risultato del cast è un comportamento indefinito.
Per evitare la sorpresa in cui T(a)
è equivalente a un cast, utilizzare la nuova sintassi di inizializzazione uniforme C++ 11, T{a}
, che è sempre un'inizializzazione, non un'espressione di trasmissione.
La grande domanda, investigare e rispondere mi ha mostrato un nuovo trucchetto di cui non ero a conoscenza in precedenza, grazie a JaredC e Dietmar per il nuovo pezzo di conoscenza!
Non terribilmente scioccante la tua specializzazione non viene chiamata se stai invocando 'Foo(a);' e mi aspetto la specializzazione 'Foo ()' per essere licenziato. –
WhozCraig
@WhozCraig Sono d'accordo, ero disperata perché non aveva senso. – JaredC
Fa, ovviamente, sparare, se invochi direttamente 'Foo()', ma non è proprio quello che stai alla fine cercando, senza dubbio. –
WhozCraig