c++ - que - tipo por referencia c#
¿Cuándo no se puede convertir un objeto a una referencia? (2)
Deseo compilar la siguiente línea de código de http://code.google.com/p/enhsim :
enh::eout << enh::setw(26);
gcc da el siguiente error:
error: no match for ''operator<<'' in ''enh::eout << enh::setw(26)''
Pero la clase EnhSimOutput
(de la cual enh::eout
es una instancia) declara:
EnhSimOutput& operator<< (setw& p);
Este problema desaparece si implemento una versión de la operación que acepta el objeto por valor:
EnhSimOutput& operator<< (setw p);
o si creo el objeto enh::setw
como local, es decir:
enh::setw wValue(26);
enh::eout << wValue;
Mi pregunta es esta: ¿por qué gcc no selecciona la versión "por referencia" del operador para empezar?
Los desarrolladores que escribieron este código claramente lo compilaron, pero el gcc predeterminado se rehúsa a hacerlo. ¿Por qué hay una diferencia entre un objeto declarado por separado como una variable local y un local creado en línea?
Mi suposición es que EnhSimOutput& operator<< (setw& p);
pasa por referencia no constante, pero el valor 26 es "const" en el sentido de que no se puede modificar. Intente configurarlo en EnhSimOutput& operator<< (const setw& p);
o tratar
int nNumber = 26;
enh::eout << enh::setw(nNumber);
El valor enh::setw(26);
es un rvalue En realidad, los temporales así son valores. Los valores R tienen propiedades especiales. Una de ellas es que su dirección no puede tomarse ( &enh::setw(26);
es ilegal), y generalmente no pueden vincularse a referencias a no-const (algunos temporales pueden enlazarse a referencias a no-const, pero estos se someten a reglas especiales: Llamar a funciones miembro sobre objetos temporales y atrapar objetos de excepción por referencia a no-const. En este último caso, el valor par temporal es un valor l ).
Hay dos tipos de expresiones: lvalues que denotan objetos (que a su vez pueden almacenar un valor) o funciones, y rvalues que deben representar valores leídos de un objeto o representados por temporarios, literales numerales y constantes del enumerador. En C ++ 03, para poder pasar dichos valores a una función que acepta su valor por referencia, existe una regla de que pueden ser aceptados por referencia-a-const: setw const& p
lo aceptará. Es decir, tendrías que declarar a tu operador así:
EnhSimOutput& operator<< (setw const& p);
Eso es un poco desafortunado, porque no puedes eliminar la ambigüedad de los valores l constantes (objetos que creaste en la pila usando const enh::setw e(26);
por ejemplo) y enh::setw(26);
no const o const (como enh::setw(26);
que es un temporal no const). Además, si lo hace, el parámetro no puede haber llamado a funciones de miembros no const, porque es una referencia-a-const. Por esa razón, C ++ 1x, la próxima versión de C ++, introduce un nuevo tipo de referencia, las denominadas referencias-rvalue que corrige eso.
El compilador de Microsoft Visual C ++ vincula valores a las referencias a no const, pero emite una advertencia al hacerlo (debe usar al menos el nivel de advertencia 4 para que se muestre). Eso es desafortunado, porque los problemas aumentan cuando se transfiere a otros compiladores que son más estrictos en el cumplimiento de estándares.