为什么不能用模板数组引用?

_ZGq 2018-12-11 12:30:38
我写了这样一个函数:
template<typename T>
T max_r(T (&arr)[],int size,bool(*compare_func_if_x_less_than_y)(T,T)=[](T x,T y)->bool{return x<y;}){
//...
}

结果编译器报错了:
[Error] parameter 'arr' includes reference to array of unknown bound 'T []'

我想是T类型不确定,无法在编译期判断引用的大小的原因吧。
是这个原因吗?
如果是,要怎样改呢?(要求还是一个模板引用数组,如果C++不允许,为什么不允许呢?)如果不是这个原因,那是什么引起了这个错误呢?
...全文
319 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
www_adintr_com 2018-12-12
  • 打赏
  • 举报
回复
引用 7 楼 weixin_41461277 的回复:
[quote=引用 6 楼 www_adintr_com 的回复:] 我说的引用需要指明数组的维度, 你这个不是引用的吗! 没有通过引用的时候, 数组参数是退化成指针的, T arr[] 等价于 T* arr
其实我是想说lambda表达式的问题。min_v函数也有这样的lambda表达式做函数指针,怎么没有警告或错误呢?(我开了[-Wall])[/quote] 额, 那可能是我的编译器不行把 但是你把这个参数类型定义成函数指针还是会限制用户可以使用的类型吧, 比如函数对象什么的.
srhouyu 2018-12-11
  • 打赏
  • 举报
回复
引用 7 楼 weixin_41461277 的回复:
[quote=引用 6 楼 www_adintr_com 的回复:] 我说的引用需要指明数组的维度, 你这个不是引用的吗! 没有通过引用的时候, 数组参数是退化成指针的, T arr[] 等价于 T* arr
其实我是想说lambda表达式的问题。min_v函数也有这样的lambda表达式做函数指针,怎么没有警告或错误呢?(我开了[-Wall])[/quote] lambda表达式本就可以隐式转换为函数指针,当然前提是你没有捕捉变量。你要是真写C++的话,还是建议你用std::function。
_ZGq 2018-12-11
  • 打赏
  • 举报
回复
引用 6 楼 www_adintr_com 的回复:
我说的引用需要指明数组的维度, 你这个不是引用的吗!
没有通过引用的时候, 数组参数是退化成指针的, T arr[] 等价于 T* arr

其实我是想说lambda表达式的问题。min_v函数也有这样的lambda表达式做函数指针,怎么没有警告或错误呢?(我开了[-Wall])
www_adintr_com 2018-12-11
  • 打赏
  • 举报
回复
引用 3 楼 weixin_41461277 的回复:
[quote=引用 1 楼 www_adintr_com 的回复:] 使用数组的引用你必须指明数组的维度, 如果要用于任意维度的, 可以再增加一个模板参数来表示维度. 还有, lambda 表达式是不能转换成一个函数指针类型的.
那为什么我上面写的
template<typename T>
T min_v(T arr[],int size,bool(*compare_func_if_x_less_than_y)(T,T)=[](T x,T y)->bool{return x<y;}){
	T min_value=arr[0];
	for(int i=1;i<size;++i){
		if(arr[i]>min_value) min_value=arr[i];
	}
	return min_value;
}
可以成立呢?编译器不会报错。 [/quote] 我说的引用需要指明数组的维度, 你这个不是引用的吗! 没有通过引用的时候, 数组参数是退化成指针的, T arr[] 等价于 T* arr
_ZGq 2018-12-11
  • 打赏
  • 举报
回复
我意识到一个问题:我没有把compare_func_if_x_less_than_y用上,改了一下,结果如下:
template<typename T,int size>
T& max_r(T (&arr)[size],bool(*compare_func_if_x_less_than_y)(T,T)=[](T x,T y)->bool{return x<y;}){
T max_value=arr[0],max_number=0;
for(int i=1;i<size;++i){
if(compare_func_is_x_less_than_y(max_value,arr[i])) max_value=arr[i],max_number=i;
}
return arr[max_number];
}
_ZGq 2018-12-11
  • 打赏
  • 举报
回复
template<typename T,int size>
T& max_r(T (&arr)[size],bool(*compare_func_if_x_less_than_y)(T,T)=[](T x,T y)->bool{return x<y;}){ //刚才代码中少了一个&,补上
T max_value=arr[0],max_number=0;
for(int i=1;i<size;++i){
if(arr[i]>max_value) max_value=arr[i],max_number=i;
}
return arr[max_number];
}
_ZGq 2018-12-11
  • 打赏
  • 举报
回复
引用 1 楼 www_adintr_com 的回复:
使用数组的引用你必须指明数组的维度, 如果要用于任意维度的, 可以再增加一个模板参数来表示维度.
还有, lambda 表达式是不能转换成一个函数指针类型的.

那为什么我上面写的
template<typename T>
T min_v(T arr[],int size,bool(*compare_func_if_x_less_than_y)(T,T)=[](T x,T y)->bool{return x<y;}){
T min_value=arr[0];
for(int i=1;i<size;++i){
if(arr[i]>min_value) min_value=arr[i];
}
return min_value;
}
可以成立呢?编译器不会报错。



引用 2 楼 srhouyu 的回复:
这跟模板没关系。

数组的引用要求很严格,形参和实参得长度一样,例如你定义float max(float (&arr)[100])的话,就得传入一个float arr[100],传入float arr[101]都不行。所以编译器根本不会接受你这种不定长数组的无理要求。建议你把size写在模板参数中,这样才是定长的。只不过这样每一个不同的size都是一个不同的函数版本。

正确姿势:

template<typename T, int SIZE>
T max_r(T (&arr)[SIZE],bool(*compare_func_if_x_less_than_y)(T,T)=[](T x,T y)->bool{return x<y;}){
//...
}

我根据实际需要稍微修改了一下,也测试通过了:
template<typename T,int size>
T max_r(T (&arr)[size],bool(*compare_func_if_x_less_than_y)(T,T)=[](T x,T y)->bool{return x<y;}){
T max_value=arr[0],max_number=0;
for(int i=1;i<size;++i){
if(arr[i]>max_value) max_value=arr[i],max_number=i;
}
return arr[max_number];
}
谢谢
srhouyu 2018-12-11
  • 打赏
  • 举报
回复
这跟模板没关系。 数组的引用要求很严格,形参和实参得长度一样,例如你定义float max(float (&arr)[100])的话,就得传入一个float arr[100],传入float arr[101]都不行。所以编译器根本不会接受你这种不定长数组的无理要求。建议你把size写在模板参数中,这样才是定长的。只不过这样每一个不同的size都是一个不同的函数版本。 正确姿势:

template<typename T, int SIZE>
T max_r(T (&arr)[SIZE],bool(*compare_func_if_x_less_than_y)(T,T)=[](T x,T y)->bool{return x<y;}){
    //...
}
www_adintr_com 2018-12-11
  • 打赏
  • 举报
回复
使用数组的引用你必须指明数组的维度, 如果要用于任意维度的, 可以再增加一个模板参数来表示维度. 还有, lambda 表达式是不能转换成一个函数指针类型的.

#include <stdio.h>
#include <algorithm>

template<typename T, int N, typename Pred = std::less<T> >
T max_r(T (&arr)[N], Pred pred = std::less<T>())
{
	T max = arr[0];

	for (int i = 1; i < N; ++i)
	{
		if (pred(max, arr[i]))
		{
			max = arr[i];
		}
	}

	return max;
}

int main(int argc, char **argv)
{
	int a[] = { 1, 2, 3, 10, 4, 5 };
	
	printf("%d\n", max_r(a));
}
说明:本文档所有内容来源于网络 https://www.numpy.org.cn/user/ 目录 1. NUMPY 介绍 1 1.1 什么是 NUMPY? 1 1.2 为什么 NUMPY 这么快? 3 1.3 还有谁在使用 NUMPY? 3 2. 快速入门教程 4 2.1 先决条件 4 2.2 基础知识 4 2.2.1一个例子 5 2.2.2 数组创建 6 2.2.3 打印数组 8 2.2.4 基本操作 10 2.2.5 通函数 13 2.2.6 索引、切片和迭代 14 2.3 形状操纵 18 2.3.1改变数组的形状 18 2.3.2 将不同数组堆叠在一起 20 2.3.3 将一个数组拆分成几个较小的数组 22 2.4 拷贝和视图 23 2.4.1 完全不复制 23 2.4.2 视图或浅拷贝 24 2.4.3 深拷贝 25 2.4.4 功能和方法概述 26 2.5 LESS 基础 26 广播(Broadcasting)规则 27 2.6 花式索引和索引技巧 27 2.6.1使用索引数组进行索引 27 2.6.2使用布尔数组进行索引 31 2.6.3 ix_()函数 34 2.6.4使用字符串建立索引 37 2.7线性代数 37 简单数组操作 37 2.8技巧和提示 38 2.8.1“自动”整形 39 2.8.2矢量堆叠 39 2.8.3直方图 40 2.9进一步阅读 41 3. NUMPY 基础知识 42 3.1 数据类型 42 3.1.1 数组类型之间的转换 42 3.1.2 数组标量 45 3.1.3 溢出错误 46 3.1.4 扩展精度 47 3.2 创建数组 47 3.2.1 简介 48 3.2.2 将Python array_like对象转换为Numpy数组 48 3.2.3 Numpy原生数组的创建 48 3.2.4 从磁盘读取数组 50 3.3 NUMPY与输入输出 51 3.3.1 定义输入 51 3.3.2 将行拆分为列 52 3.3.3 跳过直线并选择列 54 3.3.4 选择数据的类型 55 3.3.5 设置名称 56 3.3.6 调整转换 59 3.3.7 快捷方式函数 62 3.4 索引 62 3.4.1 赋值与引用 63 3.4.2 单个元素索引 63 3.4.3 其他索引选项 64 3.4.4 索引数组 65 3.4.5 索引多维数组 66 3.4.6 布尔或“掩码”索引数组 67 3.4.7 将索引数组与切片组合 69 3.4.8 结构索引工具 70 3.4.9 为索引数组赋值 71 3.4.10 在程序中处理可变数量的索引 72 3.5 广播 73 3.6 字节交换 78 3.6.1字节排序和ndarrays简介 78 3.6.2 更改字节顺序 80 3.7 结构化数组 82 3.7.1 介绍 82 3.7.2 结构化数据类型 83 3.7.3 索引和分配给结构化数组 88 3.7.4 记录数组 96 3.7.5 Recarray Helper 函数 98 3.8编写自定义数组容器 116 3.9子类化NDARRAY 124 3.9.1 介绍 124 3.9.2 视图投影 125 3.9.3 从模板创建 126 3.9.4 视图投影与从模板创建的关系 126 3.9.5 子类化的含义 126 3.9.6 简单示例 —— 向ndarray添加额外属性 132 3.9.7 稍微更现实的例子 —— 添加到现有数组的属性 134 3.9.8 __array_ufunc__ 对于ufuncs 135 3.9.9 __array_wrap__用于ufuncs和其他函数 139 3.9.10 额外的坑 —— 自定义的 __del__ 方法和 ndarray.base 142 3.9.11 子类和下游兼容性 143 4. 其他杂项 144 4.1 IEEE 754 浮点特殊值 144 4.2 NUMPY 如何处理数字异常的 146 4.3 示例 146 4.4 连接到 C 的方式 147 4.4.1 不借助任何工具, 手动打包你的C语言代码。 147 4.4.2 Cython 148 4.4.3 ctypes 148 4.4.4 SWIG(自动包装发生器) 149 4.4.5 scipy.weave 149 4.4.6 Psyco 149 5. 与MATLAB比较 149 5.1 介绍 150 5.2 一些关键的差异 150 5.3 'ARRAY'或'MATRIX'?我应该使用哪个? 151 5.3.1 简答 151 5.3.2 长答案 151 5.4 MATLAB 和 NUMPY粗略的功能对应表 153 5.4.1 一般功能的对应表 153 5.4.2 线性代数功能对应表 154 5.5 备注 161 5.6 自定义您的环境 163 5.7 链接 164 6. 从源代码构建 164 6.1 先决条件 164 6.2 基本安装 164 6.3 测试 165 并行构建 165 6.4 FORTRAN ABI不匹配 165 6.4.1 选择fortran编译器 166 6.4.2 如何检查BLAS / LAPACK /地图集ABI 166 6.5 加速BLAS / LAPACK库 166 6.5.1 BLAS 166 6.5.2 LAPACK 167 6.5.3 禁用ATLAS和其他加速库 167 6.6 提供额外的编译器标志 168 6.7 使用ATLAS支持构建 168 7. 使用NUMPY的C-API 168 7.1 如何扩展NUMPY 168 7.1.1 编写扩展模板 169 7.1.2 必需的子程序 169 7.1.3 定义函数 171 7.1.4 处理数组对象 175 7.1.5 示例 180 7.2 使用PYTHON作为胶水 182 7.2.1 从Python调用其他编译库 183 7.2.2 手工生成的包装器 183 7.2.3 f2py 184 7.2.4 用Cython 191 7.2.5 ctypes 196 7.2.6 您可能会觉得有用的其他工具 206 7.3 编写自己的UFUNC 208 7.3.1 创建一个新的ufunc 208 7.3.2 示例非ufunc扩展名 209 7.3.3 一种dtype的NumPy ufunc示例 215 7.3.4 示例具有多个dtypes的NumPy ufunc 221 7.3.5 示例具有多个参数/返回值的NumPy ufunc 230 7.3.6 示例带有结构化数组dtype参数的NumPy ufunc 235 7.4 深入的知识 241 7.4.1 迭代数组中的元素 242 7.4.2 用户定义的数据类型 246 7.4.3 在C中对ndarray进行子类型化 249

15,440

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 非技术区
社区管理员
  • 非技术区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧