不能直接用模板形参限制传入数组最大长度,因为函数参数中数组会退化为指针而丢失长度信息;正确做法是使用非类型模板参数绑定数组引用类型,如template void f(const int (&arr)[n]),使n在编译期推导并支持static_assert检查。

不能直接用模板形参限制“传入数组”的最大长度,因为 C++ 中函数参数里的数组会退化为指针,根本拿不到长度信息。 你想约束的其实是「编译期已知大小的数组类型」,不是运行时传进来的那块内存。
为什么 void f(int arr[]) 无法获取数组长度
这是 C/C++ 的底层规则:函数参数声明为 int arr[] 或 int arr[10],编译器一律当作 int* arr 处理。所以在函数体内 sizeof(arr) 返回的是指针大小(通常是 8),不是数组总字节数。
- 即使你写
void f(int arr[100]),调用f(data)时传入长度为 200 的数组也不会报错 - 模板也无法从这个退化后的指针反推原始长度
- 所谓“限制传入数组长度”,本质是误用了术语——你真正能约束的,是模板实例化时的**数组类型**
正确做法:用非类型模板参数绑定数组长度
要让编译器在实例化时检查并固化长度,必须把数组作为引用类型传入,并用非类型模板参数捕获其尺寸:
template <size_t n>
void process_array(const int (&arr)[N]) {
static_assert(N <ul>
<li>参数 <code>const int (&arr)[N]</code> 是对「长度为 N 的 int 数组」的引用,不会退化</li>
<li>调用 <code>process_array(my_arr)</code> 时,N 自动推导为 <code>my_arr</code> 的声明长度</li>
<li>
<code>static_assert</code> 在编译期触发,超过阈值直接报错,不生成代码</li>
<li>如果想支持不同元素类型,可加 <code>typename T</code>: <code>template <typename t size_t n> void f(const T (&arr)[N])</typename></code>
</li>
</ul>
<h3>常见误用:<code>std::array</code> 和 <code>vector</code> 不适用此约束</h3>
<p>如果你传的是 <code>std::array<int></int></code> 或 <code>std::vector<int></int></code>,上面的引用模板不会匹配:</p>
<ul>
<li>
<code>std::array</code> 是类模板,它的长度是其模板参数,但对象本身是值类型,不是原生数组;需单独重载或特化</li>
<li>
<code>std::vector</code> 长度完全运行时决定,任何编译期限制都无效——它根本不带长度信息进模板形参</li>
<li>试图对 <code>vector</code> 做 <code>static_assert(v.size() 会失败,因为 <code>v.size()</code> 不是常量表达式</code>
</li>
</ul>
<p>真正需要“限制最大长度”的场景,几乎都指向栈上固定尺寸缓冲区(比如协议包、临时缓存),这时必须用原生数组 + 引用形参 + 非类型模板参数组合,其他路径都会绕回运行时检查,失去编译期保障的意义。</p></size_t>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











