std::is_integral等是编译期类型特征工具,定义于,通过模板偏特化实现零开销类型查询,支持_v/_t/::value三种用法,仅接受类型而非值。

什么是 std::is_integral 这类东西?
它不是运行时函数,是编译期“提问工具”:你写 std::is_integral_v<int></int>,编译器立刻告诉你 true;写 std::is_integral_v<:string></:string>,立刻得 false。背后没有函数调用、没有开销,只有类型检查和模板偏特化机制在工作。
- 它们定义在
<type_traits></type_traits>头文件里,C++11 起就有 - 所有标准 trait 都带
_v(变量模板)、_t(别名模板)、::value三种用法,推荐优先用_v,更直白 - 别试图对变量调用,比如
std::is_pointer_v(x)是错的——它只认类型,不认值:std::is_pointer_v<decltype></decltype>才对
怎么用 std::enable_if 做函数重载筛选?
这是最常踩坑的场景:想让某个函数只接受整数类型,但写错了就直接编译失败,而不是静默跳过。
- 错误写法:
template<typename t> void f(T x, std::enable_if_t<:is_integral_v>><em> = nullptr)</em></:is_integral_v></typename>
问题在于:当T不是整数时,std::enable_if_t<false></false>展开成void,而void非法,SFINAE 失效,报硬错误 - 正确写法:把约束放在模板参数列表末尾,或用 C++20 的
requires更清晰 - 推荐替代(C++17 起):
template<typename t> std::enable_if_t<:is_integral_v>> f(T x) { ... }</:is_integral_v></typename>
这样返回类型推导失败时,属于 SFINAE 可恢复范围
std::remove_reference_t 和 std::decay_t 差在哪?
都用来“剥掉引用”,但剥得有多干净,决定了后续类型匹配是否准确。
-
std::remove_reference_t<int></int>→int;std::remove_reference_t<const int></const>→const int -
std::decay_t<const int></const>→int(去掉 const + 引用 + 数组转指针 + 函数转指针) - 实际写泛型代码时,传参常用
decay_t模拟“实参真正类型”,比如完美转发前做类型判断 - 但若你明确只想解引用、保留 cv 限定符,就该用
remove_reference_t或配std::remove_cv_t
为什么 std::is_same_v<t int></t> 有时总返回 false?
常见于模板参数未被正确推导,或你误把表达式当类型用了。
立即学习“C++免费学习笔记(深入)”;
- 典型错误:
auto x = 42; static_assert(std::is_same_v<decltype int>);</decltype>—— 这其实是对的 - 但如果你写
static_assert(std::is_same_v<x int>)</x>,编译器直接报错:x 是变量,不是类型 - 更隐蔽的是模板中:
template<typename t> void g(T&& t) { static_assert(std::is_same_v<t int>); }</t></typename>
调用g(42)时,T是int;但调用g(i)(i 是int&)时,T是int&,断言就崩了 - 解决办法:需要判断“底层类型”时,先过一遍
std::decay_t<t></t>
类型萃取本身不难,难的是它总在你没意识到的地方悄悄改变语义——比如 std::forward 内部靠 remove_reference_t,std::make_shared 依赖 decay_t,漏掉一层,转发就失效,或者类型擦除出错。










