función de plantilla y boost::remove_reference

Estoy rastreando un error del compilador de C++ que no puedo descifrar. Lo he reducido a este código:

#include <boost/config.hpp>
#include <boost/type_traits/remove_reference.hpp>

template<typename T> inline const T bar( T in )
{
    typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type nonref;
    const nonref* inPtr = &in;
    return *inPtr;
}

class Foo
{
};

int main()
{
    Foo foo;
    const Foo& ref = bar< Foo& >( foo );
}

lo que resulta en:

tt.cpp: In function ‘const T bar(T) [with T = Foo&]’:
tt.cpp:19:39:   instantiated from here
tt.cpp:9:13: error: invalid initialization of reference of type ‘Foo&’ from expression of type ‘const nonref {aka const Foo}’

¿Cuál es el problema real aquí? ¿Por qué falta la const en el valor de retorno? Necesito remove_reference ya que el código real lo requiere.

preguntado el 22 de mayo de 12 a las 14:05

3 Respuestas

La aplicación de const a un tipo de referencia no hace nada. Necesitas hacer el argumento de la plantilla. const foo &, o elimine la referencia y luego vuelva a agregar ambos const y la referencia en la propia firma de la función.

Vea también ¿Cuándo debo usar remove_reference y add_reference? particularmente el segundo párrafo.

contestado el 23 de mayo de 17 a las 13:05

Usando VisualStudio 2008 me sale el siguiente error

error C2440: 'return' : cannot convert from 'const nonref' to 'Foo &'

Cambio de bate a

template<typename T> inline const typename boost::remove_reference<T>::type& bar( T in )
{
    typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type nonref;
    const nonref* inPtr = &in;
    return *inPtr;
}

corrige esto y el código compila.

contestado el 22 de mayo de 12 a las 15:05

Pero, sutilmente, el tipo de retorno de la función aún no es const, que probablemente no es lo que ella pretende. - Patataswatter

Pues… ahora vuelve por valor, no por referencia. Quizás casualmente este es otro contexto donde const se ignora Personalmente me replantearía un diseño que requiera const para ser añadido debajo de una referencia. - Patataswatter

Volviendo const T de su función no hace lo que espera. Por tu código entiendo que esperas que regrese const Foo&, cual es una referencia a un objeto inmutable de tipo Foo.

Pero cuando T is Foo&, la expresion const T significa una referencia inmutable a un objeto de tipo Foo. Dado que las referencias son siempre inmutables, ¡la parte const simplemente se elimina (de acuerdo con el párrafo 8.3.2 de la especificación)! Es decir, su función devuelve Foo& y no const Foo& y eso es lo que el compilador intenta decirte.

contestado el 22 de mayo de 12 a las 15:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.