A veces nos gusta tomar un parámetro grande por referencia, y también para hacer la referencia const si es posible para advertir que es un parámetro de entrada. Pero al hacer la referencia const, el compilador se permite a sí mismo convertir datos si es del tipo incorrecto. Esto significa que no es tan eficiente, pero más preocupante es el hecho de que creo que me estoy refiriendo a los datos originales; quizás tomaré su dirección, sin darme cuenta de que estoy, en efecto, tomando la dirección de un temporal.¿Es posible tomar un parámetro por referencia constante, mientras se prohíben las conversiones para que no se pasen los temporales?
La llamada a bar
en este código falla. Esto es deseable, porque la referencia no es del tipo correcto. La llamada al bar_const
también es del tipo incorrecto, pero se compila silenciosamente. Esto no es deseable para mí.
#include<vector>
using namespace std;
int vi;
void foo(int &) { }
void bar(long &) { }
void bar_const(const long &) { }
int main() {
foo(vi);
// bar(vi); // compiler error, as expected/desired
bar_const(vi);
}
¿Cuál es la forma más segura de pasar una referencia liviana y de solo lectura? Estoy tentado de crear una nueva plantilla tipo referencia.
(Obviamente, int
y long
son muy pequeños tipos. Pero han sido atrapados con estructuras más grandes que se pueden convertir el uno al otro. No quiero que esto suceda en silencio cuando estoy tomando una referencia constante. a veces, marcando los constructores como explícita ayuda, pero eso no es lo ideal)
actualización: me imagino un sistema como el siguiente: imagine tener dos funciones X byVal();
y X& byRef();
y el siguiente bloque de código:
X x;
const_lvalue_ref<X> a = x; // I want this to compile
const_lvalue_ref<X> b = byVal(); // I want this to fail at compile time
const_lvalue_ref<X> c = byRef(); // I want this to compile
Ese ejemplo se basa en variables locales, pero también quiero que funcione con parámetros. Quiero obtener algún tipo de mensaje de error si accidentalmente paso un ref-to-temporary o un ref-to-a-copy cuando creo que voy a pasar algo ligero, como un ref-to-lvalue. Esto es solo un "estándar de codificación": si realmente quiero permitir pasar una referencia a una temporal, entonces usaré un const X&
directo. (Estoy encontrando this piece on Boost's FOREACH para ser bastante útil.)
Usted dice que marca constructores explícita "ayuda, pero no es lo ideal" - lo que podría ser la solución ideal? Considera la respuesta de James Kanze. –
Los constructores no '' explícitos' tienen sus usos. Por ejemplo, al pasar cosas por valor, o bien con cosas como 'A a; B b = a; '. Es el caso específico donde cambiar 'T &' a 'const T &' hace más que prohibir modificaciones. Parece un poco inconsistente que agregar 'const' a una referencia hace más que solo prohibir la modificación. (Voy a comentar todas las respuestas tarde o temprano, todas son interesantes.) –