2009-01-15 18 views
7

quiero compilar la siguiente línea de código de http://code.google.com/p/enhsim:¿Cuándo no se puede convertir un objeto a una referencia?

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 los cuales enh::eout es un ejemplo) no declarar:

EnhSimOutput& operator<< (setw& p); 

Este problema desaparece si implemento una versión de la operación que acepta t l objeto de valor:

EnhSimOutput& operator<< (setw p); 

o si se crea el objeto enh::setw como local, es decir:

enh::setw wValue(26); 
enh::eout << wValue; 

Mi pregunta es la siguiente: ¿por qué gcc no selecciona la versión "por referencia" de el operador para comenzar?

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?

Respuesta

13

enh::setw(26); El valor es un valor p . En realidad, los temporales así son valores. Los valores R tienen propiedades especiales. Una de ellas es que no se puede tomar su dirección (&enh::setw(26); es ilegal), y generalmente no pueden vincularse a referencias a no const (algunos temporales pueden enlazar a referencias a non-const, pero estos se someten a reglas especiales : Llamar a funciones miembro en objetos temporales y atrapar objetos de excepción por referencia a no const. En este último caso, el valor par temporal es lvalue).

Hay dos tipos de expresiones: lvalues ​​ que denotan objetos (que a su vez puede almacenar un valor) o funciones, y rvalues ​​ que están destinados a representar los valores leídos de un objeto o representados por los temporales, el numeral literales 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ía. Es decir, que tendría que declarar el operador de la siguiente manera:

EnhSimOutput& operator<< (setw const& p); 

que es un poco desafortunado, porque no se puede eliminar la ambigüedad lvalues ​​constantes (objetos que hemos creado en la pila usando const enh::setw e(26); por ejemplo) y no constante o const rvalues ​​(como enh::setw(26); que no es const temporal). 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, llamada rvalue-references que corrige eso.


El Microsoft Visual C++ compilador se une a rvalues ​​referencias no constante, pero da una advertencia al hacer que (usted tiene que utilizar al menos el nivel de alerta 4 para que aparezca). Eso es desafortunado, porque los problemas aumentan cuando se transfiere a otros compiladores que son más estrictos en el cumplimiento de estándares.

+0

Cambiar el operador a una referencia constante soluciona el problema correctamente. Gracias por la información sobre valores. No tengo idea de por qué se compiló el código para otra persona. El proyecto está destinado a Windows ... tal vez todos estén usando un compilador * no suficiente * compilador. Ni idea. –

+0

litb: Creo que te refieres a "reference-to-const" en tu oración "Además, si sigues eso, el parámetro no puede haber llamado a las funciones miembro non-const, porque es una referencia-a-nonconst. " –

+0

Matt: las versiones anteriores de MS Visual C++ vincularían incorrectamente los temporales a ref-to-non-const. Creo que esto se corrigió en MSVC++ 2005. –

3

Supongo 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. Pruebe a ajustarla a EnhSimOutput& operator<< (const setw& p);

o tratar

int nNumber = 26; 
enh::eout << enh::setw(nNumber); 
+0

-1, porque el problema no tiene nada que ver con que 26 sea un literal. El problema es que 'enh :: setw (number)' es temporal y, por lo tanto, no puede vincularse a una referencia no constante. –

Cuestiones relacionadas