std::is_pointer和std::is_reference严格按标准定义判别:前者仅对t*(含cv修饰、函数指针等)返回true,后者对t&/t&&均返回true;二者互斥,因c++类型系统禁止同一类型同时为指针和引用。

std::is_pointer 和 std::is_reference 是两个完全独立的类型特征,不能互换、不能覆盖、也不能靠“看起来像”来判断——它们只认标准定义的类型构成。
std::is_pointer 只识别 T* 形式,不认 void* 以外的 cv 修饰变体?
不对。它识别所有指向对象或函数的指针类型,包括 const int*、volatile char*、void*、int(*)(double)(函数指针),但不识别 T&、T&&、std::shared_ptr<t></t> 或数组类型(如 int[5])。
常见误判场景:
- 把
int[]当作指针:实际是数组类型,std::is_pointer_v<int></int>为false - 忽略顶层 cv 修饰不影响结果:
std::is_pointer_v<int const></int>仍为true(因为指针本身是int*) -
std::is_pointer_v<decltype></decltype>是false——nullptr是字面量,类型是std::nullptr_t,不是指针类型
std::is_reference 只对 & 和 && 生效,且区分左值/右值引用?
它不区分左值/右值引用——std::is_reference_v<t></t> 和 std::is_reference_v<t></t> 都返回 true。但它对任何带引用符号的类型都敏感,哪怕嵌套在模板中。
典型陷阱:
-
std::is_reference_v<int></int>→true,但std::is_reference_v<int></int>(折叠后仍是int&)也返回true;而std::is_reference_v<int></int>同样为true -
std::is_reference_v<decltype></decltype>若func()返回int&,结果为true;若返回int(非引用),则为false——注意引用折叠和 decltype 的规则 -
std::is_reference_v<:reference_wrapper>></:reference_wrapper>是false:它只是个包装器,不是语言级引用类型
为什么 is_pointer::value 和 is_reference::value 永远不会同时为 true?
因为 C++ 标准禁止指针类型与引用类型重叠:没有合法类型既是 T* 又是 U&。编译器在类型系统层面就隔离了这两条路径。
但要注意边界情况:
-
std::is_pointer_v<:remove_reference_t>></:remove_reference_t>→ 先去引用得,再判断指针,结果为 <code>false - 想统一检测“可解引用类型”,不能只靠这两个 trait:还需考虑
std::shared_ptr、std::unique_ptr、自定义迭代器等,应配合std::is_indirectly_readable(C++20)或 SFINAE 检测*t - 模板偏特化时若同时匹配
T*和T&,必须显式分离,否则会冲突或被主模板兜底
最易被忽略的一点:这两个 trait 对“退化类型”(decayed types)完全无感——比如 decltype(auto) 或模板参数推导中,int& 可能被自动退化成 int,此时 std::is_reference_v 就查不到原来那个引用了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











