std::is_pointer 仅对内置对象指针类型(如 t、void)返回 true,对函数指针、智能指针、引用、数组、nullptr_t 均返回 false;使用时应配合 std::remove_cvref_t 并优先采用 _v 后缀。

std::is_pointer 的基本用法和编译期判断逻辑
std::is_pointer 是 C++11 引入的类型特征(type trait),用于在编译期判断一个类型是否为「裸指针」(即 T* 形式,不含引用、数组、函数指针等)。它不关心指针指向什么,只看类型本身是否是「对象指针类型」。
关键点:它返回的是 std::integral_constant<bool value></bool>,不是 bool;必须用 ::value 或 ::operator bool() 获取结果,否则会编译失败或被当作类型参与推导。
-
std::is_pointer<int>::value</int>→true -
std::is_pointer<int>::value</int>→false -
std::is_pointer<void>::value</void>→true(void* 也算指针) -
std::is_pointer<int>::value</int>→false(函数指针不满足std::is_pointer,要用std::is_function+ 去引用/去指针组合判断)
为什么 std::is_pointer 对函数指针和智能指针都返回 false
这是设计使然:std::is_pointer 仅对「内置指针类型」特化为 true。函数指针(如 int(*)())、成员函数指针(int (C::*)())、std::unique_ptr、std::shared_ptr 都不是内置指针,因此 std::is_pointer<t>::value</t> 全为 false。
常见误判场景:把 std::shared_ptr<int></int> 当作指针传入模板,期望 std::is_pointer 触发分支——实际不会,必须改用 std::is_constructible、std::is_convertible 或自定义 trait 判断“是否可解引用”语义。
- 函数指针需先用
std::remove_pointer_t提取类型,再配合std::is_function - 智能指针建议用
std::is_same_v<t std::shared_ptr>></t>或 SFINAE 检查operator->是否存在 -
std::is_pointer<decltype>::value</decltype>→false,因为&func类型是函数类型,不是函数指针;要写成static_cast<void>(nullptr)</void>这类显式函数指针才匹配
在模板中安全使用 std::is_pointer 的典型模式
直接在 if constexpr 中用 std::is_pointer_v<t></t> 最简洁(C++17 起推荐用 _v 后缀替代 ::value)。但要注意:模板参数 T 若未去引用/去 const,可能导致误判。
例如 T = int* const&,std::is_pointer_v<t></t> 仍是 true(顶层 cv/ref 不影响指针本质),但若 T 是 int&,则为 false。真正需要“底层是否为指针”,应先 std::remove_reference_t<:remove_cv_t>></:remove_cv_t> 再判断。
- 推荐写法:
if constexpr (std::is_pointer_v<:remove_reference_t>>>)</:remove_reference_t> - 错误写法:
if constexpr (std::is_pointer_v<t>)</t>——T&永远不是指针类型,无论 T 是什么 - 别在非 constexpr 上下文中用
std::is_pointer做运行时分支,它没有运行时开销,但语法上不允许(如普通if)
容易忽略的兼容性与陷阱
std::is_pointer 在所有标准版本中行为一致,但某些旧编译器(如 GCC 4.8 之前)对成员指针支持不全;更隐蔽的问题是:它对 nullptr_t 返回 false,而 nullptr 可隐式转换为任意指针类型——这意味着你不能靠 std::is_pointer 来“过滤掉空值”,它只管类型,不管值。
-
std::is_pointer_v<decltype></decltype>→false(nullptr类型是std::nullptr_t) -
std::is_pointer_v<:nullptr_t></:nullptr_t>→false,不可用于 SFINAE 约束指针参数是否可接受nullptr - 跨平台时注意:MSVC 对未完全实例化的模板中
std::is_pointer的诊断可能更宽松,Clang/GCC 更严格,建议始终用std::remove_cvref_t(C++20)或手动去除修饰再判断
真正想识别“能像指针一样用”的类型,std::is_pointer 只是起点;后续往往得叠加 std::is_destructible、std::is_nothrow_copy_constructible,甚至 std::is_invocable_r 来验证解引用行为——单靠一个 trait 做不了精准语义识别。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











