2010-04-04 17 views
5

¿Hay alguna forma en que pueda construir un nuevo objeto a partir del objeto dado si los parámetros de plantilla de ambos objetos son idénticos en tiempo de ejecución? Por ejemplo:Clases de plantillas C++ y construcción de copias

tengo una clase de plantilla con la declaración:

template<typename _Type1, typename _Type2> class Object; 

A continuación, tengo dos instancias de la plantilla:

template class Object<char, int>; 
template class Object<wchar_t, wint_t>; 

Ahora, quiero escribir una función miembro, tales como:

template<typename _Type1, typename _Type2> 
Object<char, int> Object<_Type1, _Type2>::toCharObject() { 
    if(__gnu_cxx::__are_same<_Type1, char>::__value) 
     return *this; 
    else { 
     //Perform some kind of conversion and return an Object<char, int> 
    } 
} 

he intentado un par de técnicas, como el uso __gnu_cxx::__enable_if<__gnu_cxx::__are_same<_Type1, char>::__value, _Type1>::__type en un constructor de copia para la clase Oject, pero yo sigo corriendo en el error:

error: conversion from ‘Object<wchar_t, wint_t>’ to non-scalar type ‘Object<char, int>’ requested 

¿No hay manera de que pueda hacer esto? ¡Cualquier ayuda será apreciada!

+2

Los nombres de su tipo de plantilla no son válidos. Los subrayados seguidos de los identificadores de letras mayúsculas ** están reservados para su uso por parte de la implementación **. Podrían chocar con los nombres definidos por el compilador o la biblioteca estándar. – jalf

+0

@jaif: No te preocupes demasiado por los nombres tipográficos. Simplemente los elegí arbitrariamente para el ejemplo. Todo mi código está realmente definido en un espacio de nombres diferente, por lo que no debería haber conflictos. – themoondothshine

+3

Los espacios de nombres no son los nombres de los problemas, como _Tipo1 están reservados bajo TODAS las circunstancias (pueden ser macros, por ejemplo), y en este caso es poco probable que la implementación los utilice. ¿O estás diciendo que lo que publicaste no es el código real que está causando tu problema? Bueno, no hagas eso tampoco. –

Respuesta

4

Lo que debe funcionar, el problema es que el compilador está realizando una comprobación de tipo en la parte return *this, incluso si los tipos no son iguales (de ahí el error de compilación). Solo use return (Object<char, int>)(*this); y debería estar bien - la única vez que se ejecutará ese código es cuando los tipos son los mismos de todos modos, por lo que el elenco no hace nada más que trabajar alrededor del error de compilación.

Como alternativa, puede utilizar la plantilla de especialización:

template <class _Type1, class _Type2> 
Object<char, int> toCharObject(Object<_Type1, _Type2> obj) 
{ 
    // Do conversion and return 
} 

// Specialisation when types are equal 
template <> 
Object<char, int> toCharObject(Object<char, int> obj) 
{ 
    return obj; 
} 

Ésta es una función gratuita como se puede ver. Puedes hacerlo como una función miembro, pero es más complicado porque no puedes especializar la función de miembro individual, tienes que especializar a toda la clase. Puedes evitar eso al factorizar el código no especializado, pero eso es realmente feo, y esto funciona igual de bien.

+0

@Peter: ¡Has dado en el clavo! Debería haber pensado en la especialización de plantillas antes ... Lo he usado ya en bastantes lugares. Duh !!! ¡Gracias una tonelada! – themoondothshine

+0

@Peter: ... pero de alguna manera no puedo hacer que el casting funcione. Si intento lanzarlo, el compilador informa "error: conversión inválida". – themoondothshine

+0

Esto es lo que funcionó: 'return Object (* reinterpret_cast *> (this))' – themoondothshine

Cuestiones relacionadas