C++如何使用std::is_bounded_array判断定长数组?

11次阅读

std::is_bounded_array 是编译期类型判断工具,仅对 t[n] 返回 true,需配合 decltype 使用,对指针、std::array 等均返回 false,且必须在 constexpr 或模板上下文中使用。

C++ 如何使用 std::is_bounded_array 判断定长数组?

std::is_bounded_array 是个编译期判断工具,不是运行时函数

它只能在模板元编程或 constexpr 上下文中起作用,不能像普通函数那样传入变量调用。你写 std::is_bounded_array<decltype>::value</decltype> 是对的,但写 std::is_bounded_array<arr></arr>std::is_bounded_array<int></int>(漏掉 decltype 或类型包)就会编译失败。

  • 必须用 decltype 获取数组的完整类型(含维度),例如 int[3]char[10]
  • 裸写 int[5] 作为模板参数合法,但实际中几乎总是从变量推导,所以 decltype 更安全
  • 它对指针、std::arraystd::vector 全部返回 false —— 只认 C 风格定长数组类型

常见误判:把指针或退化数组当定长数组

函数参数里写 void f(int arr[5]),实际形参类型是 int*decltype(arr) 是指针,std::is_bounded_array 必然为 false。C++ 不允许函数参数以数组类型传递(会自动退化)。

  • 检查数组长度?得靠模板推导:template<size_t n> void f(int (&arr)[N]) {static_assert(std::is_bounded_array<decltype>::value); }</decltype></size_t>
  • std::is_pointer_v<decltype></decltype> 对比确认是否已退化
  • VS 和 GCC 对 int a[5]decltype(a) 一致,但 Clang 在某些模板上下文中可能更严格,建议统一用 std::is_bounded_array_v<decltype></decltype>(C++17 起支持 _v 后缀)

和 std::is_unbounded_array 的区别与配合使用

std::is_unbounded_array 判断的是 T[] 这种不带长度的声明(极少用,仅在声明外部数组或某些 ABI 场景出现),而 std::is_bounded_array 判断 T[N]。两者互斥,且都为 false 时大概率是其他类型。

  • 典型场景:写类型擦除容器时,想区分「定长数组」和「动态分配内存」,需同时排除 std::is_pointerstd::is_array(它对两者都为 true
  • std::is_array_v<t></t> 是父集判断,std::is_bounded_array_v<t></t> 是其子集;别用错层级
  • 注意:std::is_bounded_array_v<int></int>falsestd::is_unbounded_array_v<int></int> 才是 true

constexpr 场景下怎么安全用

if constexpr 中做分支是最常见用途,但要注意模板参数必须能被常量表达式求值。比如局部变量数组可以,但函数参数若未以引用方式传入就不行。

立即学习 C++ 免费学习笔记(深入)”;

  • 正确:template<typename t> constexpr auto get_size() { if constexpr (std::is_bounded_array_v<t>) return std::extent_v<t>; else return size_t{0}; }</t></t></typename>
  • 错误:void g(int x[5]) {if constexpr (std::is_bounded_array_v<decltype>) …… }</decltype> —— x 是指针,decltype(x) 不是数组类型
  • std::extent_v<t></t>std::rank_v<t></t> 必须搭配 std::is_bounded_array_v<t></t> 使用,否则对非数组类型行为未定义

类型系统里没有“运行时数组长度”这个概念,所有判断都发生在编译期;一旦类型推导出错,错误信息往往绕过直觉,盯住 decltype 输出和 std::is_array 的结果比反复试更容易定位。

text=ZqhQzanResources