const_cast dans le modèle. Y at-il un modificateur unconst?
-
19-09-2019 - |
Question
J'ai une classe de modèle comme celui-ci:
template<T>
class MyClass
{
T* data;
}
Parfois, je veux utiliser la classe avec un type T constante comme suit:
MyClass<const MyObject> mci;
mais je veux modifier les données à l'aide const_cast<MyObject*>data
(il est important de pourquoi, mais MyClass
est une classe de pointeur intelligent de comptage de référence qui maintient le compte de référence dans les données elles-mêmes. MyObject
est dérivé d'un certain type qui contient le compte.
Les données ne doit pas être modifiée, mais le nombre doit être modifié par le pointeur intelligent.).
Y at-il un moyen de supprimer const-ness de T
? Code fictionnelle:
const_cast<unconst T>(data)
La solution
La façon la plus simple serait ici de faire le compte de référence mutable.
Toutefois, si vous êtes intéressé par la façon dont il travaillerait avec le const_cast
, réimplémentant alors le remove_const
de boost devrait être assez 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();
Autres conseils
Vous avez la réponse. const_cast fonctionne dans les deux sens:
char* a;
const char* b;
a = const_cast<char*>(b);
b = const_cast<const char*>(a); // not strictly necessarily, just here for illustration
Quant à vous question spécifique, avez-vous considéré le mot-clé mutable? Il permet une variable membre à modifier dans une méthode const.
class foo {
mutable int x;
public:
inc_when_const() const { ++x; }
dec_when_const() const { --x; }
};
Faire le compte de référence mutable dans la classe gérée par votre pointeur intrusif. Ceci est tout à fait raisonnable, et reflète « constness logique » correctement exactement - à savoir changer le compteur de référence de l'objet ne reflète aucun changement dans l'état de l'objet lui-même. En d'autres termes, le nombre de références est pas logiquement partie de l'objet - l'objet se trouve être un endroit pratique pour stocker ces données semi-indépendant
.Si vous pouvez utiliser Boost, la bibliothèque de type fournit la caractères remove_const métafonction qui fait cela.
Voici mon C ++ 11 fonction unconst
template
.
Si vous l'utilisez, vous flirtent avec le titre comportement non défini . Vous avez été averti .
// 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;
}