开发者

Removing const-ness from a type inside template function

开发者 https://www.devze.com 2023-03-08 03:05 出处:网络
void foo (void *p); // library function; can\'t edit template<typename T> void Remove (T *p) 开发者_如何学Python{
void foo (void *p); // library function; can't edit

template<typename T>
void Remove (T *p)
开发者_如何学Python{
  // 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()`


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


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


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()`


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号