Matt Joiner
Matt Joiner

Reputation: 118500

Change only parts of a type in a C++ template

Purpose and craziness aside, is there a way to achieve this in C++?

template <typename P>
void Q void_cast(P Q *p) const
{
    return static_cast<P Q *>(p);
}

I'm effectively trying to cast a pointer to a void pointer type whilst keeping any const, restrict and other qualifiers (denoted by Q).

I was under the impression there was stuff in the C++ standard library (or less desirably, in Boost), that allowed you to "tweak" properties of types, with finer granularity than say const_cast or static_cast.

Upvotes: 3

Views: 282

Answers (3)

Roger Pate
Roger Pate

Reputation:

template<class From>
typename copy_rpcv<void, From*>::type void_cast(From *p) {
  return p;  // implicit conversion works
}

With a little TMP utility:

// "copy ref/pointer/const/volatile"
template<class To, class From>
struct copy_rpcv {
  typedef To type;
};
template<class To, class From> struct copy_rpcv<To, From&        > { typedef typename copy_rpcv<To, From>::type&         type; };
template<class To, class From> struct copy_rpcv<To, From*        > { typedef typename copy_rpcv<To, From>::type*         type; };
template<class To, class From> struct copy_rpcv<To, From const   > { typedef typename copy_rpcv<To, From>::type const    type; };
template<class To, class From> struct copy_rpcv<To, From volatile> { typedef typename copy_rpcv<To, From>::type volatile type; };

You'd have to add another case for the restrict specifier; it probably would work just fine, but I don't know how it, as a non-standard feature in 03 (is it in 0x?), interacts:

template<class To, class From> struct copy_rpcv<To, From* restrict> { typedef typename copy_rpcv<To, From>::type* restrict type; };

My solution differs from Anthony's in preserving "nested" type info:

int *const *const p = 0;
void *const *const v = void_cast(p);

Upvotes: 1

MarcoH
MarcoH

Reputation: 33

In the boost type traits lib are some tools to remove qulifiers

http://www.boost.org/doc/libs/1_44_0/libs/type_traits/doc/html/index.html

Upvotes: 1

Anthony Williams
Anthony Williams

Reputation: 68571

So, you want const X* -> const void*, volatile X* -> volatile void*, etc.

You can do this with a set of overloads:

template<typename P>
void* void_cast(P* p)
{
    return p;
}

template<typename P>
void const* void_cast(P const* p)
{
    return p;
}

template<typename P>
void volatile* void_cast(P volatile* p)
{
    return p;
}

template<typename P>
void const volatile* void_cast(P const volatile* p)
{
    return p;
}

The new type traits are things like add_const, add_volatile, remove_const and remove_volatile. They work for transforming the cv-qualifiers of a type in a known way, not for applying the cv-qualifiers of one type to another.

Upvotes: 7

Related Questions