Reputation: 33589
Does the C++11/14/17 standard library have a way to cast an object to a different type but with the same cv-qualifiers as the original object? E. g.
char* ptr;
const char* cptr;
type_cast<void*>(ptr)
should yield the type void*
type_cast<void*>(cptr)
should yield the type const void*
Upvotes: 3
Views: 277
Reputation: 63124
Not in the standard library, but it is certainly possible to implement it yourself:
namespace detail_base_type_cast {
template <class In, class Out>
struct copy_cv {
using type = Out;
};
template <class In, class Out>
struct copy_cv<In const, Out &> {
using type = Out const &;
};
template <class In, class Out>
struct copy_cv<In volatile, Out &> {
using type = Out volatile &;
};
template <class In, class Out>
struct copy_cv<In const volatile, Out &> {
using type = Out const volatile &;
};
}
template <class Out, class In>
typename detail_base_type_cast::copy_cv<In, Out>::type
base_type_cast(In &obj) {
return obj; // Implicit derived-to-base conversion
}
Upvotes: 3
Reputation: 4052
It looks like there is no C++17 or earlier stdlib way to do what you want in single function/statement. However it looks like there might be something like this in C++20: https://en.cppreference.com/w/cpp/types/common_reference (not available in any of the compilers yet it seems).
EDIT: but it's available in Ranges lib so if you already use it, you can use ranges::common_reference_t
instead.
But for your use case, either overloading on argument constness or using if constexpr
might be a better option.
I.e. something like:
template<typename T>
auto foo(T &bar) {
// lots of code
if constexpr(std::is_const_v<T>) {
return static_cast<const Foo&>(bar);
} else {
return static_cast<Foo&>(bar);
}
}
Upvotes: -1