应使用 std::is_pointer_v 在编译期判断类型是否为指针,它比 std::is_pointer::value 更简洁;注意需先用 std::remove_reference_t 和 std::remove_cv_t 剥离引用和 cv 限定符以确保准确性。

怎么判断一个类型是不是指针
直接用 std::is_pointer_v<t></t>,别手写特化。它在编译期返回 true 或 false,比 std::is_pointer<t>::value</t> 更简洁,C++17 起推荐用带 _v 后缀的变量模板。
常见错误是拿运行时值去判断:比如写 if (is_pointer_v<decltype>)</decltype> 却忘了 x 是个变量,decltype(x) 得到的是带引用/const 的完整类型——int&、const char* 都不是指针类型,但 const char* 本身是指针,而 int& 不是。这时候得先去掉引用和 cv 限定符:std::is_pointer_v<:remove_reference_t>>> </:remove_reference_t> 才稳妥。
- 指针判别只看类型本身,不看所指对象是否有效
-
std::is_pointer_v<void></void>是true,std::is_pointer_v<int></int>是false(数组不是指针) - 模板推导中慎用,避免因引用折叠导致误判
如何让函数只接受整数类型参数
用 std::is_integral_v 做 SFINAE 或 static_assert 检查。比起手动列出 int、long、unsigned short 等,它自动覆盖所有标准整型(含 char、bool、std::size_t 等),也兼容用户自定义的 std::is_integral 特化(极少需要)。
容易踩的坑是把 std::is_integral_v<t></t> 和 std::is_arithmetic_v<t></t> 混用:后者还包括浮点类型,如果你真要“只能是整数”,用前者;如果允许 float,才用后者。
立即学习“C++免费学习笔记(深入)”;
- 在函数模板里配合
requires(C++20)最干净:template<typename t> requires std::is_integral_v<t> void f(T);</t></typename> - C++17 可用
std::enable_if_t,但注意别漏掉typename = void默认模板参数 -
static_assert适合非模板函数或调试阶段快速拦截
为什么 std::remove_const 对 const 引用没用
因为 std::remove_const<t></t> 只移除顶层 const,而 const int& 的 const 是修饰引用所绑定的对象,属于底层 const,它根本不归 remove_const 管。真正该用的是 std::remove_reference_t 先解引用,再套一层 std::remove_cv_t。
典型场景:你想从 const std::string& 中提取出裸的 std::string 类型做类型擦除或容器存储。直接 std::remove_const_t<const std::string></const> 还是 const std::string&,毫无变化。
- 正确链式写法:
std::remove_cv_t<:remove_reference_t>></:remove_reference_t> - 更通用的替代是
std::decay_t<t></t>,它同时做去引用、去 const/volatile、数组转指针、函数转指针,但要注意副作用:会把int[3]变成int*,可能不是你想要的 - 别依赖
auto推导来“绕过”这个问题——auto x = expr;的x类型仍带 const/ref,萃取得靠显式类型操作
移动语义里怎么安全调用 std::is_trivially_move_constructible
这个 trait 判断类型能否用 memcpy 级别方式移动,不是“有没有移动构造函数”。很多自定义类即使写了 T(T&&),只要内部有虚函数、虚基类、non-trivial 析构函数等,就不是 trivially move constructible。
实际用处在于:做内存拷贝优化前必须确认该 trait 为 true,否则 std::memcpy 替代移动会导致未定义行为。比如实现自己的 vector,reallocate 时若元素满足该条件,可跳过逐个移动,直接 bulk copy。
- 注意它不检查移动赋值,只管构造;要同时保证移动赋值也 trivial,还得查
std::is_trivially_move_assignable_v -
std::is_trivially_copyable_v<t></t>是更强条件,满足它一定满足 move 相关 trait,但反过来不成立 - 别在运行时分支里用它做逻辑分发——它是编译期常量,只能用于模板分支或
if constexpr
类型萃取不是拼凑 trait 的游戏,关键是理解每个 trait 判定的边界在哪。比如 is_pointer 不看值、remove_const 不动底层 const、is_trivially_move_constructible 和“有没有移动构造函数”根本不是一回事——这些地方一错,编译器不会报错,但行为可能完全偏离预期。









