2009-10-04 6 views
5

que tienen una clase de plantilla como esta:const_cast en la plantilla. ¿Hay algún modificador incondicional?

template<T> 
class MyClass 
{ 
    T* data; 
} 

A veces, quiero utilizar la clase con un tipo T constante de la siguiente manera:

MyClass<const MyObject> mci; 

pero desea modificar los datos utilizando const_cast<MyObject*>data (no es importante por qué, pero MyClass es una clase de puntero inteligente de conteo de referencia que mantiene el recuento de referencias en los datos. MyObject se deriva de algún tipo que contiene el recuento Los datos no se deben modificar, pero el recuento debe ser modificado por el puntero inteligente.)

¿Hay alguna manera de eliminar la const-ness de T? Código ficticio:

const_cast<unconst T>(data) 

?

Respuesta

11

La manera más sencilla aquí sería hacer que el recuento de referencias sea mutable.

Sin embargo, si usted está interesado en la forma en que trabajaría con el const_cast, a continuación, reimplementar de remove_const impulso debe ser muy sencillo:

template <class T> 
struct RemoveConst 
{ 
    typedef T type; 
}; 

template <class T> 
struct RemoveConst<const T> 
{ 
    typedef T type; 
}; 

const_cast<typename RemoveConst<T>::type*>(t)->inc(); 
+0

Gracias por explicar cómo me funciona remove_const. – danatel

+3

@danatel: Realmente no quiere usar remove_const.La modificación de un valor constante mediante la eliminación de la constness es un comportamiento indefinido. Desea usar __mutable__ en la variable de recuento. –

+0

:-) Uso mutable. No necesitaba una solución a mi problema, el problema estaba allí solo como una ilustración (por favor, lea la publicación original). Tenía curiosidad de saber si hay una forma de eliminar la constancia. – danatel

5

Tiene la respuesta. const_cast funciona en ambas direcciones:

char* a; 
const char* b; 

a = const_cast<char*>(b); 
b = const_cast<const char*>(a); // not strictly necessarily, just here for illustration 

En cuanto a ti cuestión específica, ¿ha considerado la palabra clave mutable? Permite modificar una variable miembro dentro de un método const.

class foo { 
    mutable int x; 
public: 
    inc_when_const() const { ++x; } 
    dec_when_const() const { --x; } 
}; 
+0

Pero esta es una clase de plantilla. T es const algo. La pregunta es: ¿cómo creo algo que no sea de T? – danatel

+1

+1 Mutable es la respuesta aquí. – UncleBens

3

Si puede usar Boost, la biblioteca de tipos Rasgos proporciona la metafunción remove_const que hace eso.

+0

Desafortunadamente, en este proyecto no puedo usar Boost. Pero si hubiera habido una manera fácil de hacer esto en C++ estándar, entonces nadie escribiría remove_const. Por lo tanto, no hay tal camino. – danatel

+0

¿Has leído las otras respuestas? Boost es solo una versión con metatabla, solo usa const_cast y quita const o mutable, como dijo jumcchellio. – GManNickG

4

Haga que el recuento de referencia sea mutable en la clase administrada por su puntero intrusivo. Esto es completamente razonable y refleja la "constidad lógica" exactamente de la manera correcta, es decir, cambiar el recuento de referencias del objeto no refleja ningún cambio en el estado del objeto en sí. En otras palabras, el recuento de referencias no es lógicamente parte del objeto; el objeto resulta ser un lugar conveniente para almacenar estos datos semirrelatados.

0

Aquí es mi C++ 11 unconst función template.

Si lo usa, usted está coqueteando con undefined behavior. Usted ha estado advertido.

// on Ubuntu (and probably others) compile and test with               
// g++ -std=c++11 test.c && ./a.out ; echo $?        

template < class T > T & unconst (T const & t) { 
    return const_cast < T & > (t) ; 
} 

// demonstration of use 

struct { 
    const int n = 4; 
} s; 

int main() { 
    unconst (s.n) = 5; 
    return s.n; 
} 
+0

Creo que esto sería más simple y tiene el mismo efecto: 'plantilla T & unconst (T const & t) {return const_cast (t);}'. – alfC

+0

¡Gracias! Es más simple y parece funcionar. Me preguntaba cuál era la diferencia entre 'typename' y' class'. – mpb