2009-10-04 11 views
5

Ho una classe template in questo modo:const_cast nel modello. C'è un modificatore inconstante?

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

A volte, voglio usare la classe con un tipo costante T come segue:

MyClass<const MyObject> mci; 

ma voglio modificare i dati utilizzando const_cast<MyObject*>data (non è importante perché, ma MyClass è una classe di puntatore intelligente di conteggio di riferimento che conserva il conteggio dei riferimenti nei dati stessi. I dati non devono essere modificati ma il conteggio deve essere modificato dal puntatore intelligente.).

C'è un modo per rimuovere la costanza da T? Codice di fantasia:

const_cast<unconst T>(data) 

?

risposta

11

Il modo più semplice sarebbe quello di rendere mutabile il conteggio dei riferimenti.

Tuttavia, se siete interessati a come avrebbe funzionato con la const_cast, poi reimplementare di remove_const spinta dovrebbe essere abbastanza semplice:

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

Grazie per aver spiegato come funziona remove_const. – danatel

+3

@danatel: davvero non vuoi usare remove_const.La modifica di un valore const mediante il cast della costanza è un comportamento non definito. Si desidera utilizzare __mutable__ sulla variabile refcount. –

+0

:-) Io uso mutabile. Non avevo bisogno di una soluzione al mio problema, il problema era lì solo come illustrazione (si prega di leggere il post originale) - Ero curioso di sapere se c'è un modo per rimuovere la costanza. – danatel

5

Hai la risposta. const_cast funziona in entrambe le direzioni:

char* a; 
const char* b; 

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

Per quanto riguarda il problema specifico, hai considerato la parola chiave mutabile? Permette di modificare una variabile membro all'interno di un metodo const.

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

Ma questa è una classe modello. T è const qualcosa. La domanda è: come posso creare qualcosa nonconst da T? – danatel

+1

+1 Mutevole è la risposta qui. – UncleBens

3

Se è possibile utilizzare Boost, la libreria dei tipi Tratti fornisce la remove_const metafunction che lo fa.

+0

Sfortunatamente, su questo progetto non posso usare Boost. Ma se ci fosse stato un modo semplice per farlo nel C++ standard, nessuno avrebbe scritto remove_const. Quindi non esiste un modo simile. – danatel

+0

Hai letto le altre risposte? Boost è solo una versione meta-templata, basta usare const_cast e rimuovere const da esso o mutabile, come diceva jumcchellio. – GManNickG

4

Rende mutabile il conteggio dei riferimenti nella classe gestita dal puntatore intrusivo. Questo è del tutto ragionevole e riflette la "coerenza logica" in modo esatto - cioè, la modifica del conteggio dei riferimenti dell'oggetto non riflette alcun cambiamento nello stato dell'oggetto stesso. In altre parole, il conteggio dei riferimenti non è logicamente parte dell'oggetto - l'oggetto sembra essere un posto conveniente in cui archiviare questi dati semi-non correlati.

0

Ecco il mio C++ 11 unconst funzione template.

Se lo si utilizza, si stanno flirtando con undefined behavior. Sei stato avvertito.

// 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

Penso che sarebbe più semplice e ha lo stesso effetto: 'modello T & unconst (T const & t) {return const_cast (t);}'. – alfC

+0

Grazie! È più semplice e sembra funzionare. Mi chiedevo quale fosse la differenza tra 'typename' e' class'. – mpb