iammilind
iammilind

Reputation: 69978

Removing const-ness from a type inside template function

void foo (void *p); // library function; can't edit

template<typename T>
void Remove (T *p)
{
  // main code
  foo(p); // Can we remove const ness of T here ?
}

I have multiple functions like Remove(), it can be called with const T* also, which will not match with foo(void*). Without overloading/specializing Remove() can I remove the constness of T*? ... Usage:

const int *p;
Remove(p); // error related to `foo()`

Upvotes: 1

Views: 7622

Answers (4)

p_a_c
p_a_c

Reputation: 285

You might also first do a static_cast to const void * then const_cast that to void *:

template<typename T>
void Remove (T *p)
{
    foo(const_cast<void*> (static_cast <const void*> (p)));
}

It's admittedly quite ugly.

Upvotes: 0

Cubbi
Cubbi

Reputation: 47408

If you really need it, there's a boost/C++0x metafunction for that:

template<typename T>
void Remove (T *p)
{
    foo( const_cast< typename std::remove_const<T>::type *> (p) );
}

test: https://ideone.com/L6urU

Upvotes: 3

Mark B
Mark B

Reputation: 96233

That would effectively be taking a pointer-to-const-object, and removing the constness thus making it (foo) able to mutate the object. This would be inconsistent with the actual exposed interface which implies that it works equally (and expectedly) on any type.

Not only that, but it would allow you to call it with the address of an actually const object which would be undefined behavior.

Instead, you should, if absolutely needed (and guarantee that the object isn't const) remove the constness before calling the template function so that it works as expected (not mutating const types).

const A *p;
Remove(const_cast<A*>(p)); // error for `foo()`

Upvotes: 2

Konrad Rudolph
Konrad Rudolph

Reputation: 545518

How about:

template <typename T>
struct nonconst {
    static T& value(T& value) { return value; }
};

template <typename T>
struct nonconst<T const> {
    static T& value(T const& value) { return const_cast<T&>(value); }
};

Use it as follows:

template<typename T>
void Remove (T* p) {
    foo(&nonconst<T>::value(*p));
}

(Or specialise the template further for (non-)const pointers.)

Upvotes: 2

Related Questions