2010-11-23 15 views
5

Considere el siguiente programa:plantilla de tipo constante operador de conversión no funciona bajo Linux (gcc)

#include <iostream> 

template<int s> 
class Pack 
{ 
public: 
    Pack(){} 
    char data[s]; 
    template<typename X> operator X&(){ return *reinterpret_cast<X*>(data); } 
    template<typename X> operator X const&()const{ return *reinterpret_cast<const X*>(data); } 
}; 

int main() 
{ 
    const Pack<8> p; 
    const double d(p); 
    std::cout<<d<<std::endl; 
} 

Se compila bien en Windows. bajo Linux me sale:

test.cc: In function ‘int main()’: 
test.cc:17: error: passing ‘const Pack<8>’ as ‘this’ argument of ‘Pack<s>::operator X&() [with X = double, int s = 8]’ discards qualifiers 

¿Por qué? ¿Por qué no está tomando el operador de conversión de tipo const? ¿Cómo puedo solucionar esto y todavía tengo el operador de conversión de tipo de plantilla conveniente (en const y no const versión). Gracias!

+0

Tengo un error diferente con GCC (y Comeau). No encuentra ninguna función de conversión. Probablemente porque está buscando una función de conversión como 'operator double()' y no encuentra una adecuada (porque las proporcionadas también tienen una referencia). - Si es una buena idea en primer lugar, ¿por qué no utilizar una función de miembro con nombre? – UncleBens

+0

@UncleBens, estás en lo correcto, mira a continuación. –

+0

No quiero usar el operador double(), porque la clase Pack debe poderse convertir a cualquier tipo. El ejemplo que publiqué se quitó para demostrar el problema. – Nathan

Respuesta

5

Según el estándar C++ 03, ese código está mal formado porque la deducción del argumento de la plantilla no podrá deducir X& o X const& contra const double.

C++ 03 omitido para indicar que la referencia se elimina del tipo de devolución de la función de conversión antes de la deducción, por lo que nunca se puede obtener una coincidencia en su caso. Para C++ 0x, this will be fixed y está incluido en el último documento de trabajo, por lo que puede compilarse con algunos compiladores que incluyen la corrección de forma retroactiva.

Su código en realidad tiene un problema diferente: GCC no aplicar esa resolución informe de defectos, y por lo tanto se compara double (que se despoja de CV-calificadores antes de la deducción!) En contra y en contra de XX const. Solo X coincide y, por lo tanto, solo esa primera función de conversión es el único candidato en una llamada con un argumento const Pack<8>, por eso GCC se queja de la falta de const en la función de conversión. Si prueba el siguiente código, funcionaría

// can't strip cv-qualifiers off "double const&" - there are no top-level 
// cv qualifiers present here! 
double const &d(p); 
+0

¿Por qué el calificador const se elimina de 'double'? ¿Por qué coincide si agrego 'operator double const &() const'? Probablemente tengas razón, pero todavía no entiendo ... –

+0

@Sven porque el 'const' no tiene ningún significado. El valor se copia de la devolución de la función de conversión de todos modos. El 'const' solo tiene un significado si está enterrado en un puntero o una referencia. Coincide cuando haces 'operator double const &' porque entonces no necesita deducción del argumento de la plantilla. El quid aquí solo es la deducción del argumento de la plantilla: * That * cede la sobrecarga de las funciones candidatas que la resolución considera al tratar con plantillas. Si escribe 'operator double const &', entonces * usted * proporciona la función candidata explícitamente, y aquí es una función candidata a la que se puede llamar. –

+0

Pruebe con un ejemplo simplier: 'template void f (T *);' si lo llama con 'f (0)' no funcionará porque la deducción del argumento de la plantilla de 'T *' contra 'int' falla. Pero si declara un 'void f (char *);' y luego llama a 'f (0)' funciona perfectamente bien. –

Cuestiones relacionadas