(ho chiesto una variante di questa domanda comp.std.C++ ma non ha ottenuto una risposta.)C++ 0x rvalue riferimenti e provvisori
Perché la chiamata a f(arg)
in questo codice di chiamata del const sovraccarico ref di f
?
void f(const std::string &); //less efficient
void f(std::string &&); //more efficient
void g(const char * arg)
{
f(arg);
}
Il mio intuito dice che il sovraccarico di f(string &&)
deve essere scelto, perché arg
deve essere convertito in una temporanea non importa cosa, e la temporanea corrisponde al riferimento rvalue meglio il riferimento lvalue.
Questo non è ciò che accade in
GCC e
MSVC (modifica: Grazie Sumant: non si verifica in GCC 4.3-4.5). In almeno
G ++ e
MSVC, qualsiasi lvalue non si associa a un argomento di riferimento del valore di riferimento, , anche se è stato creato temporaneamente un intermedio. Infatti, se il sovraccarico const ref non è presente, i compilatori diagnosticano un errore. Tuttavia, la scrittura f(arg + 0)
o f(std::string(arg))
fa sceglie il sovraccarico di riferimento di rvalue come ci si aspetterebbe.
Dalla mia lettura dello standard C++ 0x, sembra che la conversione implicita di un const-char * in una stringa debba essere considerata quando si considera se f(string &&)
è valido, proprio come quando si passa un argomento di riferimento di valore const. La sezione 13.3 (risoluzione di sovraccarico) non distingue tra refs di riferimento e riferimenti const in troppe posizioni. Inoltre, sembra che la regola che impedisce ai lvalue di legarsi ai riferimenti di valore (13.3.3.1.4/3) non dovrebbe applicarsi se c'è un temporaneo intermedio - dopo tutto, è perfettamente sicuro spostarsi dal temporaneo.
è questa:
- Me travisamento/fraintendere lo standard, in cui il comportamento attuato è il comportamento previsto, e c'è qualche buona ragione per cui il mio esempio dovrebbe comportarsi il modo in cui lo fa?
- Un errore che i produttori di compilatori hanno in qualche modo realizzato tutti? O un errore basato su strategie di implementazione comuni? O un errore, ad es. GCC (dove è stata implementata questa regola di riferimento dei valori di lvalue/rvalue), che è stata copiata da altri fornitori?
- Un difetto nello standard o una conseguenza non intenzionale o qualcosa che dovrebbe essere chiarito?
EDIT: Ho una domanda di follow-on che è legato: C++0x rvalue references - lvalues-rvalue binding
Nella situazione data, perché il sovraccarico potrebbe essere più veloce? Un oggetto stringa deve essere creato in un modo o nell'altro e un riferimento associato ad esso. – UncleBens
@UncleBens: Supponiamo che la funzione stia memorizzando il suo argomento in qualche variabile globale/variabile membro - se l'argomento è noto per essere mobile, quindi può essere spostato nella destinazione, piuttosto che copiato. – Doug