C++模板函数传入固定大小数组触发Type error问题咨询
问题解答
1. buffer的实际类型
你声明的byte buffer[100]实际类型是 byte[100](长度为100的byte数组类型),不属于byte*类型。
数组类型在绝大多数场景下会隐式退化成为指向首元素的byte*指针,但这个退化生成的指针是临时右值,不是可修改的左值。
2. 直接传参报错的原因
你的模板函数参数是byte* &buffer,这是非常量左值引用,C++语法规定非常量左值引用无法绑定到临时右值,因此直接传入数组时,退化生成的临时指针无法匹配参数类型,就会报错。
你先赋值给auto b的时候,数组退化的指针会用来初始化变量b,此时b的类型是byte*,是可修改的左值,自然可以绑定到byte* &类型的参数,所以不会报错。
3. 普通函数调用正常的原因
这个问题本质和模板无关,你遇到普通函数调用正常的情况,大概率是你写的普通函数参数为值传递的byte*,而非byte* &:
- 如果普通函数参数是
byte* buffer(值传递),退化生成的临时指针可以直接拷贝给形参,不会有绑定限制,自然调用正常 - 如果普通函数参数和模板完全一致,也是
byte* &buffer,调用时同样会报错,这不是模板的特有问题。
4. 直接传参的解决方案
方案1:调整函数参数(最推荐)
如果你的函数内部不会修改指针本身的值(比如不会执行buffer++、buffer = xxx这类修改指针指向的操作),直接把参数改为值传递即可:
template<typename T> T foo(byte* buffer){ ... }
改完之后可以直接调用foo<int>(buffer),不需要额外处理。
方案2:显式构造左值指针
如果必须保留byte* &参数(比如函数内部需要修改指针本身的值),调用时显式定义一个左值指针即可:
byte buffer[100] = {}; byte* p = buffer; foo<int>(p);
注意:如果函数内部会修改传入的指针引用的值,不要直接对数组名做强制转换后传入,数组名本身是不可修改的左值,修改它的指向会触发未定义行为,这种场景必须单独定义一个
byte*类型的变量来传参。
内容的提问来源于stack exchange,提问作者BobtheMagicMoose
相关产品推荐
相关产品推荐

