c++ std::is_same_v的意外行为

ou6hu8tu  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(116)

我写了一个函数来检查指针指向的类型,但是当你把指针设为常量时,std::is_same_v返回false。
下面是一个最小的可重复的例子,说明应该如何工作:

#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;
}

字符串
我试过将std::remove_cv_t<std::decay_t<T>>的顺序改为std::decay_t<std::remove_cv_t<T>>,甚至完全去掉std::decay_t,但仍然不起作用。我还试过用下面的代码检查std::remove_pointer_t返回的类型:

#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;
}


它返回以下内容:

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


这对我来说没有任何意义,因为类型的名称是相同的.但不是相同的类型?我使用Clang 17.0.4(C23),但我也在MSVC(C20)中测试过,也发生了同样的行为。

wooyq4lh

wooyq4lh1#

如果你的目标是检查T是否是一个指向char(或const char)的指针,你需要调整你的类型traits用法。你想在与char比较之前删除指针,但不删除const限定符。
下面是修改后的checkType函数,它可以同时用于char* 和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;
}

字符串
此修订版通过比较衰变类型(不带指针)与char和const char,正确处理了char* 和const char*。

相关问题