(pedí una variación de esta pregunta en comp.std.C++ pero no conseguir una respuesta.)C++ 0x rvalue referencias temporales y
¿Por qué la llamada a f(arg)
en este código de llamada del const Sobrecarga de ref de f
?
void f(const std::string &); //less efficient
void f(std::string &&); //more efficient
void g(const char * arg)
{
f(arg);
}
Mi intuición dice que la sobrecarga f(string &&)
debe ser elegido, porque arg
necesita ser convertido a un temporal no importa qué, y coincide con el temporal de la referencia rvalue mejor que la referencia lvalue.
Esto no es lo que sucede en
GCC y
MSVC (edit: Gracias Sumant: no ocurre en GCC 4.3-4.5). En al menos
G ++ y
MSVC, cualquier lvalue no se enlaza con un argumento de referencia rvalue, aunque haya un temporal intermedio creado. De hecho, si la sobrecarga const ref no está presente, los compiladores diagnostican un error. Sin embargo, escribiendo f(arg + 0)
o f(std::string(arg))
elige y elige la sobrecarga de referencia de valor acumulado como es de esperar.
Según mi lectura del estándar C++ 0x, parece que la conversión implícita de un const char * a una cadena debe considerarse al considerar si f(string &&)
es viable, al igual que al pasar un argumento const lvalue ref. La sección 13.3 (resolución de sobrecarga) no diferencia entre referencias rvalue y referencias de referencias en demasiados lugares. Además, parece que la regla que impide que lvalues se vincule con las referencias rvalue (13.3.3.1.4/3) no debería aplicarse si hay un intermedio temporal; después de todo, es perfectamente seguro pasar del temporal.
es la siguiente:
- Me mala lectura/malinterpretar la norma, donde el comportamiento implementado es el comportamiento previsto, y hay una buena razón por la que mi ejemplo debería comportarse de la manera que lo hace?
- ¿Algún error cometido por los fabricantes de compiladores? ¿O un error basado en estrategias comunes de implementación? O un error en, por ejemplo, GCC (donde se implementó por primera vez esta regla de enlace de referencia lvalue/rvalue), que otros proveedores copiaron?
- ¿Un defecto en el estándar, o una consecuencia involuntaria, o algo que debería aclararse?
EDIT: Tengo una pregunta de seguimiento que se relaciona: C++0x rvalue references - lvalues-rvalue binding
En la situación dada, ¿por qué la sobrecarga sería más rápida? Un objeto de cadena debe ser creado de una forma u otra y una referencia vinculada a él. – UncleBens
@UncleBens: supongamos que la función almacena su argumento en alguna variable global/variable miembro: si se sabe que el argumento es movible, puede moverse al destino en lugar de copiarse. – Doug