I was writing a function that checks what type a pointer was pointing to, but std::is_same_v returns false when you make the pointer const.
Here is a minimal reproducible example of what is supposed to work:
#include <type_traits>
template<typename T>
constexpr bool checkType() {
return std::is_same_v<std::remove_pointer_t<std::remove_cv_t<std::decay_t<T>>>, char>;
}
int main() {
static_assert(checkType<char*>(), "char* should be true");
static_assert(checkType<const char*>(), "const char* should be true");
return 0;
}
I’ve tried changing the order of std::remove_cv_t<std::decay_t<T>> to std::decay_t<std::remove_cv_t<T>> or even getting rid of std::decay_t altogether, but it still does not work. I’ve also tried checking the type returned by std::remove_pointer_t with this code:
#include <type_traits>
#include <iostream>
template<typename T>
void do_() {
#define cx std::remove_pointer_t<std::remove_cv_t<std::decay_t<T>>>
std::cout <<
"T: " << typeid(T).name() << " (" << typeid(T).raw_name() << "), " <<
"Tred: " << typeid(cx).name() << " (" << typeid(cx).raw_name() << "), \n" <<
"icb?: " << (std::is_same_v<cx, char> ? "true" : "false") << ", " <<
"iib?: " << (std::is_same_v<cx, int> ? "true" : "false")
<< "\n";
}
int main() {
do_<char>();
do_<char*>();
do_<const char*>();
do_<int>();
do_<int*>();
do_<const int*>();
return 0;
}
which returns the following:
T: char (.D), Tred: char (.D),
icb?: true, iib?: false
T: char * __ptr64 (.PEAD), Tred: char (.D),
icb?: true, iib?: false
T: char const * __ptr64 (.PEBD), Tred: char (.D),
icb?: false, iib?: false
T: int (.H), Tred: int (.H),
icb?: false, iib?: true
T: int * __ptr64 (.PEAH), Tred: int (.H),
icb?: false, iib?: true
T: int const * __ptr64 (.PEBH), Tred: int (.H),
icb?: false, iib?: false
which doesnt make any sense to me since the name of the types are the same… but arent the same type?
I’m using Clang 17.0.4 (C++23), but I’ve also tested this in MSVC (C++20) and the same behavior occurs.
>Solution :
If your goal is to check whether T is a pointer to char (or const char), you need to adjust your type traits usage. You want to remove the pointer but not the const qualifier before comparing with char.
Here’s a revised version of your checkType function that should work for both char* and const char*:
#include <type_traits>
template<typename T>
constexpr bool checkType() {
using DecayedType = std::remove_pointer_t<T>; // Only remove pointer, keep const if present
return std::is_same_v<DecayedType, char> || std::is_same_v<DecayedType, const char>;
}
int main() {
static_assert(checkType<char*>(), "char* should be true");
static_assert(checkType<const char*>(), "const char* should be true");
return 0;
}
This revised version correctly handles both char* and const char* by comparing the decayed type (without the pointer) against both char and const char.