1
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()`
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 3
    possible duplicate of [const_cast in template. Is there a unconst modifier ?](http://stackoverflow.com/questions/1516563/const-cast-in-template-is-there-a-unconst-modifier) – Kristopher Johnson May 25 '11 at 14:19
  • @Kristopher, thanks. I got my answer from there. And also the idea that how `std::remove_cast` in `boost` would have been implemented. – iammilind May 25 '11 at 14:37
  • @All, thanks for reply. Finally I have ended up using the simplest solution, `foo((void*)p);` Which din't strike my mind at first. – iammilind May 26 '11 at 03:20

4 Answers4

3

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

Cubbi
  • 46,567
  • 13
  • 103
  • 169
2

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.)

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
2

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()`
Mark B
  • 95,107
  • 10
  • 109
  • 188
  • agree but that will look ugly and have to be edited at multiple places. Assume that, I am passing modifiable `const T*` only (which will not cause any UB). – iammilind May 25 '11 at 14:25
  • @iammilind And your future maintainers will thank you for the ugliness because it will be easy to track down as opposed to "Where did I accidentally do the wrong thing and had constness magically cast away without asking me". – Mark B May 25 '11 at 14:29
  • If it's a "modifiable const T*", why is it declared const? I agree with Mark B, this looks like a set-up for trouble down the road. – Nemo May 25 '11 at 14:31
0

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.

p_a_c
  • 275
  • 2
  • 7