Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: Zaelsius en 16 de Febrero de 2008, 04:48:53 PM

Título: GCC 4 y los rvalues como parámetros a función
Publicado por: Zaelsius en 16 de Febrero de 2008, 04:48:53 PM
Hola, resulta que estoy portando el código de una aplicación C++ de VC 6 a GCC 4, y hay muchos lugares donde se usa un rvalue como parámetro a una función que espera una referencia del mismo tipo. Ejemplo:

void foo( int& a )
{

}


int main()
{
int a = 0;

foo( a ); // OK
foo( int(69) ); // Error
foo( (int&)int(69) ); // Error con GCC 4. GCC 3 se traga el cast.

return 0;
}


Obviamente, en el código real no se usan simples enteros, sino estructuras de datos más pesadas. En una ocasión anterior, portando una aplicación similar de VC6 a GCC 3.3, un cast me bastaba para forzar al compilador a tragarse el parámetro, pero el nuevo GCC 4 ya no admite trampa ninguna. Los casts modernos (static_cast, reinterpret_cast) también devuelven un error (lógicamente).

Aunque entiendo perfectamente porqué el código es ilegal desde el punto de vista del estándar de C++, y las diferencias entre tipos lvalue y rvalue, me gustaría saber si conocéis de algun 'workaround' para esta situación y así minimizar el código a modificar.
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: davur en 16 de Febrero de 2008, 06:24:18 PM
El código tal y como está tiene un comportamiento indefinido. Lo único más cercano a no serlo sin modificar la llamada está en cambiar el tipo del argumento de foo a const int& (porque el estándar de C++ especifica de manera deliberada que asociar un objeto temporal a una referencia a constante en la pila alarga el tiempo de vida del temporal al tiempo de vida de esa referencia), pero eso  sólo te será útil si foo no modifica su argumento, lo cual posiblemente no sea el caso porque, de serlo, éste ya sería (tendría que ser) referencia a constante en primer lugar.

No hay manera definida por el estándar del lenguaje de pasar un objeto temporal a una función que toma una referencia a no constante como parámetro. Sólo los lvalues se pueden asociar a referencias a no constantes.
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: jalbam en 17 de Febrero de 2008, 07:05:32 PM
Hola, buenas.

Perdona la ignorancia, pero ¿qué significa utilizar el signo &?

Lo he buscado por Internet pero no encuentro nada que responda a mi pregunta.

Hasta lo que yo he estudiado, sólo he utilizado el signo * en los prototipos de las funciones y en sus declaraciones para indicar que se va a recibir la dirección de memoria de una variable (un puntero). Y el signo & lo he utlizado para pasar la direccion de una variable que no es un puntero ni un vector/matriz (si lo fuera ya no haría falta ningún signo) a una función de este tipo, como es el caso de la conocida función scanf.

¿Es algo de funciones que reciben otras funciones pasadas por parámetro, callback?

Gracias. Siento la ignorancia y el off-topic :)

Saludos.
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: Pogacha en 17 de Febrero de 2008, 07:15:09 PM
Suponiendo que conozcas el tipo de parametro de foo y este sea definido se me ocurre que en algunos casos el workaround mas sencillo deberia ser usar un macro del tipo

#define foo(X) { int _temp_ =(X); foo( _temp_ );  }

Pero esto no es aplicable a todos los casos seguramente.

Lo mejor es que hables con la persona que hizo esta macana y le digas que escriba bien el codigo de forma que ande en todos los compiladores :P (seguramente a el tambien le va a interesar)

Saludos
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: Zaelsius en 17 de Febrero de 2008, 07:16:08 PM
@Jalbam: El uso del símbolo & en el código de arriba tiene que ver con el paso de parámetros a funciones por referencia (http://www.google.com/search?client=safari&rls=en-us&q=paso+de+par%C3%A1metros+por+referencia&ie=UTF-8&oe=UTF-8), una característica de C++ que no está en C.
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: jalbam en 17 de Febrero de 2008, 11:06:07 PM
Muchas gracias por la respuesta :)

La verdad es que no es la primera vez que lo veo pero no sabía qué era.

Por lo que he leido parece ser igual que cuando pasas por referencia un puntero pero esta vez es de forma "constante", sin poder modificar la variable a la que apunta.
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: Pogacha en 17 de Febrero de 2008, 11:49:07 PM
Pues no,
para que sea constante tienes que poner el modificador "const"foo(const int& variable)
{
variable = 1; // error
}

foo(int& variable)
{
variable = 1; // valido!
}
La diferencia de la referencia es que siempre apunta a un elemento valido (o almenos asi deberia)

En cambio un puntero puede apuntar a NULL

Otra diferencia es que la referencia es inoperable, no puedes desplazarte sobre ella como en un puntero (excepto que hagas unos casting a punteros y luego a referencia)

Y otra tambien es que la referencia es un elemento nuevo de C++ y aporta mas datos al compilador.

Saludos
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: Zaelsius en 18 de Febrero de 2008, 12:12:27 AM
Por cierto, gracias a Davur y Pogacha. En efecto, añadir el 'const' al parámetro por referencia soluciona la papeleta. ¡Gracias!
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: Pogacha en 18 de Febrero de 2008, 01:26:36 AM
En realidad el crédito es de Davur, yo también recién me desayuno que pasar un objeto temporal por referencia como parámetro no constante de una función es un error y no tan solo una práctica insegura.
VC6 te permite hacer esas aberraciones :X
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: LC0 en 18 de Febrero de 2008, 11:57:40 AM
Para la gente que no entienda el uso de & (en este caso jalbam), es exactamente lo mismo que usar un puntero constante. Solo que así se simplifica la sintaxis y se puede referenciar de una forma muy fácil de escribir parámetros por referencias (valga la redundancia :D).

Yo, por mi parte, acostumbrado al GCC me he quedado boquiabierto al ver que Visual C++ se traga el código de Zaelsius. ¿Has probado a modificar el parámetro a en foo (compilando desde el Visual), a ver que pasa? ¿No sería código potencialmente inseguro?
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: tamat en 18 de Febrero de 2008, 01:31:19 PM
LC0, no tiene por qué, a mi entender estas modificando una variable local de la función externa, otra cosa es que esa variable no tiene nombre, otra cosa es si no se hubiera casteado a int, porque entonces sí que estarias modificando una constante.
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: ethernet en 18 de Febrero de 2008, 11:03:16 PM
Es que en mi opinión carece de sentido tener pasar un valor constante para ser modificado, es igualq que hacer:

int a;
...
5 = a;
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: tamat en 19 de Febrero de 2008, 12:35:33 AM
si, pero al hacer int(5) creo que ya no es una constante. Yo hablo a nivel de compilador, no de concepto.
Título: GCC 4 y los rvalues como parámetros a función
Publicado por: fjfnaranjo en 19 de Febrero de 2008, 06:00:43 PM
Que hermoso sería el mundo si todos compilasemos con "-ansi -pedantic-errors"  :P