std::is_pointer仅判断类型是否为T*(含cv限定符),不关心值是否解引用或有效;std::is_reference对T&和T&&均返回true,区分左右值需用is_lvalue_reference等专用trait。

std::is_pointer 识别的是“指针类型”,不是“指向指针的值”
很多人一看到 int* 就觉得“这是个指针”,但 std::is_pointer 只对类型本身做静态判断,不关心变量是否被解引用、是否为空、是否有效。它只认模板参数是不是形如 T*(含 cv 限定符)的类型。
常见错误现象:std::is_pointer<decltype>::value</decltype> 返回 true(因为 &x 是 int* 类型),但 std::is_pointer<decltype>::value</decltype> 返回 false(因为 *p 是 int 类型)。
-
std::is_pointer<int>::value</int>→true -
std::is_pointer<int>::value</int>→true(二级指针也是指针类型) -
std::is_pointer<int>::value</int>→false -
std::is_pointer<:remove_pointer_t>>::value</:remove_pointer_t>→false(先去掉指针,剩下int)
std::is_reference 判断的是“引用类型”,且严格区分左值/右值引用
std::is_reference 对 T& 和 T&& 都返回 true,但它不区分引用类别——要区分得用 std::is_lvalue_reference 或 std::is_rvalue_reference。
容易踩的坑:函数返回类型为引用时,decltype 的行为会影响判断结果。比如 auto&& x = func(); 中,若 func() 返回 int&,则 decltype(x) 是 int&;但若 func() 返回 int,decltype(x) 是 int&&(因为是纯右值绑定)。
立即学习“C++免费学习笔记(深入)”;
-
std::is_reference<int>::value</int>→true -
std::is_reference<int>::value</int>→true -
std::is_reference<const int>::value</const>→true -
std::is_reference<int>::value</int>→false(数组不是引用)
is_pointer 和 is_reference 在模板偏特化中不能互换
这两个类型特征常用于 SFINAE 或 if constexpr 分支,但它们的语义边界非常清晰:指针可为空、可重绑定、有地址;引用必须绑定、不可空、无独立地址。混用会导致逻辑错位。
典型误用场景:想对“所有间接访问类型”统一处理,就试图用 is_pointer || is_reference 当作“间接类型”标志——这不对。std::shared_ptr<t></t>、std::optional<t></t>、甚至 T* 和 T& 的解引用行为、生命周期语义完全不同。
- 需要转发语义?优先看
std::is_reference_v<t></t>+ 引用折叠规则 - 需要判断能否做
nullptr检查?只信std::is_pointer_v<t></t> - 写通用容器迭代器 traits?别只靠这两个,还要结合
std::iterator_traits和std::is_same
注意 cv 限定符和引用折叠对判断结果的影响
cv 限定符(const/volatile)不影响 is_pointer 和 is_reference 的结果,但引用折叠会改变实际类型——尤其在模板参数推导中。
例如:函数模板 template<typename t> void f(T&&)</typename> 接收 int& 时,T 被推导为 int&,经引用折叠后 T&& 变成 int&,此时 std::is_reference_v<t></t> 是 true,但 std::is_reference_v<t></t> 也是 true(因为折叠后仍是引用)。
-
std::is_pointer<const int>::value</const>→true -
std::is_reference<const int>::value</const>→true -
std::is_reference<int>::value</int>→true(即使带&&,它仍是引用类型) - 不要对
decltype(auto)的结果直接套用这些 trait——先用std::decay_t或显式decltype确认类型
真正难的不是记住返回值,而是理解:类型特征只是编译期快照,它不反映运行时行为,也不替代语义建模。一个 int* 可能悬垂,一个 int& 可能绑定到临时对象——这些,std::is_pointer 和 std::is_reference 都管不了。



















