views:

175

answers:

4

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)

?

+4  A: 

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; }
};
jmucchiello
But this is a template class. T is const something. The question is: how do I create nonconst something from T?
danatel
+1 Mutable is the answer here.
UncleBens
+1  A: 

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

Bojan Resnik
Unfortunately, on this project I cannot use Boost. But if there had been an easy way to do this in standard C++ then nobody would write remove_const. Therefore there is no such way.
danatel
Did you read the other answers? Boost is just a meta-templated version, just use const_cast and remove const from it or mutable, like jumcchellio said.
GMan
+2  A: 

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.

Jerry Coffin
+6  A: 

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();
UncleBens
Thank you for explainig how remove_const works to me.
danatel
@danatel: You really don't want to use remove_const. Modifying a const value by casting away constness is undefined behavior. You want to use __mutable__ on the refcount variable.
Martin York
:-) I do use mutable. I didn't need a solution to my problem, the problem was there just as an illustration (please read the original post) - I was curious if there is a way to remove constantness.
danatel