Pregunta

Tengo una clase de plantilla como esta:

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 quiero modificar los datos utilizando const_cast<MyObject*>data (que no es importante qué pero MyClass es una clase de puntero inteligente cuenta de referencia que mantiene el recuento de referencia en los datos en sí. MyObject se deriva de algún tipo que contiene el recuento. Los datos no debe ser modificado, pero el recuento debe ser modificado por el puntero inteligente.).

¿Hay una manera de quitar const-dad de T? Código de ficción:

const_cast<unconst T>(data) 

¿Fue útil?

Solución

La forma más sencilla aquí sería hacer el recuento de referencia mutable.

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

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();

Otros consejos

Usted 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 la cuestión específica que, ¿ha considerado la palabra clave mutable? Permite una variable miembro a ser modificada dentro de un método const.

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

Hacer el recuento de referencia mutable en la clase administrada por el puntero intrusivo. Esto es totalmente razonable, y refleja "constness lógica" exactamente correcto - es decir, el cambio de contador de referencia del objeto no refleja ningún cambio en el estado del objeto en sí. En otras palabras, la cuenta de referencia no es lógicamente parte del objeto - el objeto sólo pasa a ser un lugar conveniente para almacenar estos datos semi-sin relación

.

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

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

Si lo usa, que están coqueteando con comportamiento indefinido . Has sido 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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top