如何编写支持std::begin/end、接收任意大小数组的C++函数?
通用数组处理函数实现与疑问解答
直接可用的通用函数实现
如果仅需支持任意大小的int数组,写法如下:
#include <iterator> // 需包含std::begin的头文件 template <std::size_t N> void func(const int (&arr)[N]) { auto arr_begin = std::begin(arr); // 完全正常工作 // 还能直接用N获取数组长度,比如遍历: for (std::size_t i = 0; i < N; ++i) { // 操作arr[i] } }
如果要支持任意元素类型的数组,把元素类型也作为模板参数即可:
template <typename T, std::size_t N> void func(const T (&arr)[N]) { auto arr_begin = std::begin(arr); }
逐个解答你的疑问
1. 模板参数写T& arr时,怎么识别是数组、怎么知道大小?
当你写template<typename T> void func(T& arr)并传入int[5]类型的数组时,编译器会自动把T推导为数组类型int[5](引用传递不会触发数组退化为指针的行为)。
此时可以通过类型特性获取数组大小:
#include <type_traits> template <typename T> void func(T& arr) { constexpr std::size_t N = std::extent_v<T>; // C++17及以上可用 auto arr_begin = std::begin(arr); }
不过显式把大小N作为模板参数(开头的写法)可读性更高,也更方便直接使用数组长度。
2. 为什么不能写成T(&arr)[]?
在C++中,未知大小的数组属于不完整类型,你无法直接引用一个不完整类型。T(&arr)[]试图定义一个指向未知大小数组的引用,编译器无法确定这个引用的具体类型——数组的大小是其类型的核心组成部分,比如int[5]和int[10]是完全不同的两种类型。
只有当模板能从实参推导数组大小时,数组引用参数才合法,也就是我们开头用模板参数N的写法,直接写T(&arr)[]属于语法错误。
3. 编写不指定固定大小的通用函数可行吗?
完全可行,就是上面展示的模板方案。模板的核心优势就是让编译器根据传入的实参自动推导数组的类型和大小,既保留了数组的完整类型信息(不会退化为指针),又实现了对任意大小数组的支持,这样std::begin就能正常工作。
内容的提问来源于stack exchange,提问作者iamnotevg
相关产品推荐
相关产品推荐

