Jaan
Jaan

Reputation: 330

Preserving constness upon a cast

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.

Upvotes: 0

Views: 149

Answers (1)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122228

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 From,typename To>
using preserve_const_t = typename preserve_const<From,To>::type;

template<typename type>
void test(type t) {
    std::cout << "t const? = " << std::is_const<decltype(t)>() << std::endl;
    preserve_const_t<type,int> 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>;

Upvotes: 1

Related Questions