Home > other >  Preserving constness upon a cast
Preserving constness upon a cast

Time:07-02

I want a way of preserving if the type is a pointer, const, etc upon a cast. See the following.

template<typename type>
void test(type t) {
    std::cout << "t const? = " << std::is_const<decltype(t)>() << std::endl;
    int x = (int) t;
    std::cout << "x const? = " << std::is_const<decltype(x)>() << std::endl;
};

int main() {
    const int x = 0;
    int y = 0;

    test<const int>(x);
    test<int>(y);
}
>>> t const? = 1
>>> x const? = 0
>>> t const? = 0
>>> x const? = 0

How do I make it so that the function prints the following? In other words, how do I make it so that if the template argument is const, x is also const?

>>> t const? = 1
>>> x const? = 1
>>> t const? = 0
>>> x const? = 0

I would like to avoid having to do anything like the following.

// bad
if constexpr (std::is_const<decltype(t)>()) {
    // do const cast
} else {
    // do non const cast
}

The specific scenario I have is I have a const or non-const void pointer and want to cast it to a pointer with a type, whilst preserving the constness.

Edit: This is a poor example. You can use type x = (type) t. I wanted a solution using type traits because this isn't a valid solution for me.

CodePudding user response:

Your example isnt the best to illustrate the actual issue to cast a void*, possibly const, to some T* with same constness, because you can simply replace the line with type x = t; to get desired output.

However, you can use a type trait:

#include <iostream>
#include <type_traits>

template <typename From,typename To>
struct preserve_const {
    using type = std::remove_const<To>::type;
};

template <typename From,typename To>
struct preserve_const<const From,To> {
    using type = const To;
};


template<typename type>
void test(type t) {
    std::cout << "t const? = " << std::is_const<decltype(t)>() << std::endl;
    typename preserve_const<type,int>::type x = t;  
    std::cout << "x const? = " << std::is_const<decltype(x)>() << std::endl;
};

int main() {
    const int x = 0;
    int y = 0;

    test<const int>(x);
    test<int>(y);
}

Or as mentioned in comments and perhaps much simpler:

template <typename type,typename T>
using the_type = std::conditional_t< std::is_const_v<type>,const T,T>;
  •  Tags:  
  • c
  • Related