Taru
Taru

Reputation: 2732

Remove const qualifiers in template C++

How can I remove all const qualifiers from a data type?

I tried to use std::remove_cv but it didnt work.

std::remove_cv< const char *>::type

Isn't it the same as std::remove_cv<char*>::type?

Thanks.

Upvotes: 1

Views: 3267

Answers (4)

Mankarse
Mankarse

Reputation: 40613

There isn't a standard way to do this, you will need to write your own:

template<typename T> struct remove_const_recursive { typedef T type; };
template<typename T> struct remove_const_recursive<T const volatile> {
    typedef typename remove_const_recursive<T>::type volatile type;
};
template<typename T> struct remove_const_recursive<T volatile> {
    typedef typename remove_const_recursive<T>::type volatile type;
};
template<typename T> struct remove_const_recursive<T const> {
    typedef typename remove_const_recursive<T>::type type;
};
template<typename T> struct remove_const_recursive<T&> {
    typedef typename remove_const_recursive<T>::type& type;
};
template<typename T> struct remove_const_recursive<T*> {
    typedef typename remove_const_recursive<T>::type* type;
};

Upvotes: 1

Olaf Dietsche
Olaf Dietsche

Reputation: 74018

You can see the differences between a constant pointer and a pointer pointing to const and the various type_traits with

#include <iostream>
#include <type_traits>

int main()
{
    std::cout << std::is_same<std::remove_const<const char*>::type, char*>::value << '\n';
    std::cout << std::is_same<std::remove_const<char* const>::type, char*>::value << '\n';
    std::cout << std::is_same<std::add_pointer<std::remove_const<std::remove_pointer<const char*>::type>::type>::type, char*>::value << '\n';
    return 0;
}

which gives as output

0
1
1

Upvotes: 0

Konrad Rudolph
Konrad Rudolph

Reputation: 545518

The trait is doing everything correctly:

const char* is the same as char const* and neither is the same as char* const. So in your case, it’s the pointee that’s const, not the pointer. And remove_const (somewhat logically) only removes the outer const, not inner ones.

If you really want to remove the constness of the pointee, you can do it like this:

using T = char const*;
using NoConstT = std::add_pointer<std::remove_cv<std::remove_pointer<T>::type>::type>::type;

(Although std::add_pointer<T>::type could be dropped in favour of the simpler T* …)

That is: remove the pointer, remove the const of the pointee, make the result a pointer again.

In fact, this is a good opportunity to use use R. Martinho Fernandes’ excellent Wheels library which provides convenient shortcuts for such nested traits:

#include <wheels/meta.h++>
using namespace wheels;
…

using NoConstT = AddPointer<RemoveCv<RemovePointer<T>>>;

Much more readable.

Upvotes: 5

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275240

Do it recursively. Match T* in a specialization, then reapply the *, etc.

Upvotes: 0

Related Questions