Pergunta

Eu tenho uma classe de modelo como esta:

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

Às vezes, quero usar a classe com um tipo T constante da seguinte maneira:

MyClass<const MyObject> mci;

Mas eu quero modificar os dados usando const_cast<MyObject*>data (não é importante por que, mas MyClass é uma classe de ponteiro inteligente de contagem de referência que mantém a contagem de referência nos próprios dados. MyObject é derivado de algum tipo que contém a contagem. Os dados não devem ser modificados, mas a contagem deve ser modificada pelo ponteiro inteligente.).

Existe uma maneira de remover a constividade de T? Código fictício:

const_cast<unconst T>(data) 

?

Foi útil?

Solução

A maneira mais simples aqui seria tornar a contagem de referência mutável.

No entanto, se você estiver interessado em como funcionaria com o const_cast, então reimplementar o impulso remove_const deve ser bastante simples:

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

Outras dicas

Você tem a resposta. const_cast funciona em ambas as direções:

char* a;
const char* b;

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

Quanto ao seu problema específico, você considerou a palavra -chave mutável? Ele permite que uma variável de membro seja modificada dentro de um método const.

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

Torne a contagem de referência mutável na classe gerenciada pelo seu ponteiro intrusivo. Isso é totalmente razoável e reflete a "constituição lógica" exatamente corretamente - ou seja, alterar a contagem de referência do objeto não reflete nenhuma alteração no estado do próprio objeto. Em outras palavras, a contagem de referência não faz parte logicamente do objeto-o objeto é um local conveniente para armazenar esses dados semi-relacionados.

Se você pode usar o Boost, a biblioteca de traços de tipo fornece o remove_const Metafunção que faz isso.

Aqui está o meu C ++ 11 unconst função template.

Se você o usar, você está flertando com comportamento indefinido. Você tem sido avisou.

// 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top