Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

const_cast in template. Is there a unconst modifier?

I have a template class like this:

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

Sometimes, I want to use the class with a constant type T as follows:

MyClass<const MyObject> mci;

but I want to modify the data using const_cast<MyObject*>data (it is not important why but MyClass is a reference count smart pointer class which keeps the reference count in the data itself. MyObject is derived from some type which contains the count. The data should not be modified but the count must be modified by the smart pointer.).

Is there a way to remove const-ness from T? Fictional code:

const_cast<unconst T>(data) 

?

like image 790
danatel Avatar asked Oct 04 '09 14:10

danatel


People also ask

Which is true for const_cast?

const_cast is one of the type casting operators. It is used to change the constant value of any object or we can say it is used to remove the constant nature of any object. const_cast can be used in programs that have any object with some constant value which need to be changed occasionally at some point.

Should I use const_cast?

As a common rule, it is very often considered a bad practice to use const_cast<>() in C++ code as it reveals (most of the time) a flaw in the design.

How do I remove const qualifier?

The statement int* c = const_cast<int>(b) returns a pointer c that refers to a without the const qualification of a . This process of using const_cast to remove the const qualification of an object is called casting away constness. Consequently the compiler does allow the function call f(c) .

How do you const cast in C++?

First create a constant variable of type int and give it some suitable size, let's say “a” and its value be 20. Then create a constant pointer, let us say “b” of the same data type and allocate it the address of our constant variable “a”.


4 Answers

The simplest way here would be to make the reference count mutable.

However, if you are interested in how it would work with the const_cast, then reimplementing boost's remove_const should be quite 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();
like image 183
UncleBens Avatar answered Sep 28 '22 21:09

UncleBens


You have the answer. const_cast works in both directions:

char* a;
const char* b;

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

As for you specific issue, have you considered the mutable keyword? It allows a member variable to be modified inside a const method.

class foo {
    mutable int x;
public:
    inc_when_const() const { ++x; }
    dec_when_const() const { --x; }
};
like image 40
jmucchiello Avatar answered Sep 29 '22 21:09

jmucchiello


Make the reference count mutable in the class managed by your intrusive pointer. This is entirely reasonable, and reflects "logical constness" exactly correctly -- i.e. changing the object's reference count does not reflect any change in the state of the object itself. In other words, the reference count isn't logically part of the object -- the object just happens to be a convenient place to store this semi-unrelated data.

like image 20
Jerry Coffin Avatar answered Oct 01 '22 21:10

Jerry Coffin


If you can use Boost, the Type Traits library provides the remove_const metafunction that does that.

like image 22
Bojan Resnik Avatar answered Sep 29 '22 21:09

Bojan Resnik