std::is_array配合static_assert可校验模板参数是否为原生数组,需用std::remove_reference_t去除引用;它不识别std::array,若需支持两者须手动组合判断;t(&&)[n]形参可天然排除指针和容器但不支持右值及多维数组;c++20概念更清晰但仍需处理cv/ref修饰。

用 std::is_array + static_assert 检查数组类型
模板参数无法直接写成「必须是数组」,但可以在实例化时主动校验。最直接的方式是在函数或类模板内部用 std::is_array 判断,并配合 static_assert 报错:
template <typename t>
void process_array(T&& arr) {
static_assert(std::is_array_v<:remove_reference_t>>,
"T must be an array type");
// ... 实际逻辑
}</:remove_reference_t></typename>
注意要先用 std::remove_reference_t 去掉引用,否则 int([5]) 这类引用类型会误判为非数组。
区分原生数组和 std::array
std::is_array 只识别 C 风格原生数组(如 int[3]、char[10]),对 std::array<int></int> 返回 false。如果想同时支持两者,得手动组合判断:
- 用
std::is_array_v<t></t>检原生数组 - 用
std::is_same_v<t std::array>></t>或更泛化的std::is_specialization_of_v<t std::array></t>(需自定义 trait)检std::array - 常见错误:把
std::vector当作数组传入——它既不是原生数组也不是std::array,static_assert会直接触发失败
用模板参数推导限制维度和元素类型
如果还需约束数组的元素类型或维度,可以显式写出数组形式的模板参数:
template <typename t std::size_t n>
void handle_fixed_array(T (&arr)[N]) {
static_assert(std::is_same_v<t int>, "only int arrays allowed");
// arr 是 int[5]、int[10] 等的左值引用,N 自动推导
}</t></typename>
这种方式天然排除指针、std::vector、std::array ——它们无法匹配 T(&)[N] 形参。但缺点是不支持右值数组(如临时 {1,2,3}),也不能处理多维数组(int[2][3] 的 T 会是 int[3],需额外偏特化)。
为什么不用概念(C++20)?
C++20 概念写起来更清晰,但要注意实际约束粒度:
template <typename t> concept IsRawArray = std::is_array_v<:remove_cvref_t>>;</:remove_cvref_t></typename>
这个概念仍需搭配 std::remove_cvref_t,否则 const int[5] 或 int([5])&& 会失败。而且概念只作用于模板参数声明处,不改变底层匹配规则——比如你仍不能靠概念让 std::vector 通过检查,它根本不会进入该重载分支。
真正容易被忽略的是数组退化行为:传入函数的原生数组参数若写成 T* 或 std::span<t></t>,类型信息就彻底丢失了,后续所有静态检查都失效。所以限制必须落在「模板参数本身能保留数组维度和 cv 属性」的位置上,而不是在运行时或中间转换后。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











