Skip to content

类型萃取 type_traits:原理与常用成员

一、什么是 type_traits

编译期「关于类型的属性/变换」的模板工具,形如常量/类型值:

  • 查询(谓词)返回 std::integral_constant<bool,v>(v 是 bool 常量),有 ::value;C++17 可 _v
  • 变换(transform)返回一个新类型,有 ::type;C++14 提供 _t 后缀。
cpp
#include <type_traits>
static_assert(std::is_integral_v<int>);          // true
static_assert(std::is_same_v<int, int>);
using T = std::remove_const_t<const int>;        // int

二、最核心:基于偏特化实现的 is_same / remove_const

cpp
template <typename T, typename U> struct is_same      : std::false_type {};
template <typename T>             struct is_same<T,T> : std::true_type  {};
// 用途:T,T 完全相同时命中偏特化 → true

template <typename T> struct remove_const      { using type = T; };
template <typename T> struct remove_const<const T> { using type = T; };  // 剥掉外层 const

std::integral_constant<bool, value>true_type/false_type 提供 value 常量 + 类型标记,方便继承复用与标签派发。

三、常用工具分类记忆

成员用途
属性查询is_integral/is_floating_point/is_enum/is_class/is_pointer/is_reference/is_const/is_volatile编译期判断类型
关系is_sameis_base_ofis_convertibleis_constructible类型关系检查
特性is_trivially_copyableis_nothrow_move_constructibleis_empty容器/算法优化依据
变性remove_referenceremove_const/volatileadd_constdecay归一类型
选择conditional<b,T,F>::typeenable_if<cond,T>common_type编译期 if / 返回类型
变换make_unsignedunderlying_type(枚举底层)、result_of/invoke_result类型运算

std::decay 语义(高频):去掉数组→指针、函数→函数指针、剥掉 cv/引用 → 即「值传参的样子」。常用于把任意传入 T 归一成能存进容器的值类型。

四、常见用途(HPC/库代码)

  1. 按特质选实现:容器根据 is_trivially_copyable decide 能否 memcpy 或必须逐一拷贝构造。
  2. 完美转发后取类型std::remove_reference_t<decltype(x)>
  3. 标签派发(tag dispatch):根据 is_arithmetic 选不同重载。
  4. if constexpr + 谓词在函数里做编译期条件分支(替代一堆 enable_if)。
  5. std::invoke_result_t 推导函数返回类型,用于模板包装返回值。

五、手写一个小 tuple 的结构(体现 type_traits 用处)

(了解即可)tuple 常实现为「递归继承」:Tuple<Head, Tail...> : private Head, Tuple<Tail...> 用继承顺序存储 + EBCO 空基类优化。面试少让人手写完整 tuple,更常见问 sizeof(tuple<>) 为什么往往不额外占——EBCO。

六、易错

  • is_same_v<T, const T>T=int 时为 false(一层 const 区分),remove_const 后比较才 true。
  • remove_reference 只剥引用不剥 const;要剥干净用 decay
  • cv 在类型外层 vs 指针所指:remove_const_p<const int*> 剥不掉所指常性——只管「顶层」。这正是混淆点,答出区别即扎实。

C++ 面试八股 · VitePress 版