使用模板"void f(int x[M][N])"时没有匹配功能"f(int[4][4])"?
No matching function for "f(int[4][4])" when using template "void f(int x[M][N])"?
#include <iostream>
template <int M, int N>
void print1(int src[M][N]) { }
void print2(int src[4][4]) { }
int main() {
int src[][4] = {
{ 1, 2, 3, 4},
{ 5, 6, 7, 8},
{ 9, 10, 11, 12},
{13, 14, 15, 16},
};
print1(src);
// gives error
// error: no matching function for call to 'print1(int [4][4])'
print2(src);
// works!
}
在上面的代码中,print2()
按预期工作,但print1()
给了我错误
错误:调用"打印(int [4][4])"没有匹配函数
我不明白,它们看起来完全相同,我只是替换了硬编码值以使用模板,以便它可以接受任何大小的数组。
为什么它不起作用?我做错了什么?
在声明中
void print2(int src[4][4])
第一个4
毫无意义。 此函数与将其声明
void print2(int src[][4])
或作为
void print2(int (*src)[4])
这是因为数组永远不会按 C 和 C++ 中的值传递。 相反,当数组传递给函数时,它会隐式转换为指向其初始元素的指针。 同样,当函数参数的类型为"T
数组"时,它会自动转换为"指向T
的指针"类型。 实际上,C 和 C++ 中没有数组类型参数。
因此,让我们考虑一下您的函数模板:
template <int M, int N>
void print1(int src[M][N])
与print2
类似,此函数模板等效于:
template <int M, int N>
void print1(int src[][N])
为了在不显式声明调用中的模板参数的情况下调用此函数,编译器必须能够从参数的类型推断出M
和N
。 M
并没有真正出现在参数列表中的任何地方,因此无法从参数中推断出它。 可以通过在调用时显式提供模板参数来调用此函数:
print1<4, 4>(src)
然而,正如我们在上面看到的,编译器可以推断出N
本身;它只是M
无法推断。 因此,您也可以通过仅提供M
参数并让编译器推断N
来进行调用:
print1<4>(src)
或者,您可以将函数模板声明为采用对数组的引用:
template <int M, int N>
void print1(int (&src)[M][N])
这将抑制数组到指针的转换。 为什么? 请记住,在前面的示例中,参数是"指向int
的一维数组的指针"。 但是,在此函数模板中,参数是"对二维数组的引用 int
"。 这两个扩展数据块(维度)都是类型的一部分,因此两者都可以由编译器推导。
但是,在大多数情况下,最好避免使用多维数组和对数组的引用,因为它们很麻烦。 两者都不适用于动态分配,并且防止发生数组到指针的转换通常很麻烦。
改用以下语法声明模板函数:
template <int M, int N>
void print1(int (&src)[M][N])
{
}
像int src[4]
这样的参数声明只是int *src
的语法糖。这同样适用于数组的数组,因此print2
实际上是:
void print2(int (*src)[4]);
也就是说,它需要一个指向int[4]
的指针。
对于您的模板函数,这归结为
template <int M, int N>
void print1(int (*src)[N]) { }
此外,当您尝试调用该函数时,您作为参数提供的数组也会衰减到指向int[4]
的指针。
由此,编译器无法推断出模板参数M
,并且找不到匹配的函数。
若要解决此问题,可以在调用函数时显式指定模板参数,或通过引用传递数组:
template <int M, int N>
void print1(int (&src)[M][N]) { }
通过引用传递时,数组的类型信息不会丢失。参数声明实际上指定了对给定维度数组的引用,并且在调用函数时,传递的数组不会衰减到指针。根据此信息,编译器可以自动推断模板参数。
说出你想使用哪个模板,例如:
print1<4,4>(src);
但请注意,模板是在编译过程中实例化的,因此您不能在其中放置变量(print1<k,m>(src)
不起作用)。
你要求编译器获取有关编译时已知数组大小的知识,然后从那里推断出 int 模板参数。
可以让编译器推导类型参数,但不能让编译器从类型(在本例中为数组大小)中获取信息并推导整数模板参数。
例如,这是有效的,因为编译器将类型推断为 int[4][4]。
template <class T>
void printFoo(T t)
{
}
像这样使用模板当然有效:
print1<4,4>(src);
您应该传递模板参数。喜欢这个:
print1<4,4>(src);
模板函数调用只能利用类型的模板参数推导。无法推断非类型模板参数。
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- 为什么在全局范围内使用"extern int a"似乎不行?
- 多态性和功能结合
- int(c) 和 c-'0' 之间的区别。C++
- 功能样式转换从 'int' 到 'ItemType' 的匹配转换
- 通过将其中一个模板更改为 muliset 后,我可以在 PBDS 排序集上使用计数功能<int>less_equal<int>
- C++ - 如何使用<int> <int>STL 算法功能在矢量<vector>中找到矢量?
- 返回处理数组的INT功能
- 功能使用INT和Float类型作为C 中的参数过载
- C 具有使用模板接受INT和INT []的功能
- 与int dataype的CIN功能混淆
- 当功能采用签名的int时,将浮点参数施放为未符号
- 将功能与"int main"问题分开(初学者)
- " invalid operands of types 'int' and 'int* const'" 来自功能的错误,来自书
- 呼叫功能时防止int施放
- 对于一对碰撞机会较低的INT的最小哈希功能是什么
- 如何对包含 pair<int,int> 元素的向量进行排序?排序是根据比较功能完成的
- 使用模板"void f(int x[M][N])"时没有匹配功能"f(int[4][4])"?
- 在 SGI STL 的实现中,文件 stl_alloc.h 中模板参数"int inst"的功能是什么?
- 多种模板<int>功能的专业化