【问题标题】:Error using Template function of one parameter (works with 2)使用一个参数的模板函数时出错(与 2 一起使用)
【发布时间】:2020-05-22 17:51:41
【问题描述】:

我正在编写一个模板函数来打印出 c 样式数组的第一个元素。如果有两个模板参数,则该函数可以工作,但如果只有一个参数,则该函数会失败。

以下代码有效。该函数正确计算 c 样式数组的大小。

template<typename dummy, typename T>
void printfunc(const T &c){
    std::cout << sizeof(c)/sizeof(c[0]) << std::endl;  //prints 5 as desired
}
int main() {

 int arr[] = {1,2,3,4,5};
 printfunc<int>(arr);
 return 0;
}

下面的代码没有。使用 g++2a 编译器出现编译错误

template<typename T>
void printfunc(const T &c){
    std::cout << sizeof(c)/sizeof(c[0]);   //Compile Error
}
int main() {

 int arr[] = {1,2,3,4,5};
 printfunc<int>(arr);
 return 0;
}

更令人困惑的是,我使用template&lt;typename T&gt; 得到的编译错误与我执行以下操作时不同:

void printfunc(const int &c){
    std::cout << sizeof(c)/sizeof(c[0]);  //compile error
}
int main() {

 int arr[] = {1,2,3,4,5};
 printfunc(arr);
 return 0;
}

我只是用调用int的函数替换了template,应该是等价的,但是编译器报错不一样。

发生了什么事?

【问题讨论】:

  • printfunc&lt;int&gt;(arr); 想要一个 int 但你传递了一个数组。
  • Stack Overflow 的惯例是您根据答案更改您的问题。问题的内容应保持已回答的内容,以便答案继续有意义。 (澄清编辑是可以的,但删除您询问的错误是不行的。)当您的问题得到您满意的回答时,您应该接受最佳答案并且将“已回答”编辑到您的主题中。存在已接受的答案表示该问题已得到回答。

标签: c++ arrays templates


【解决方案1】:

发生的情况是您尝试使用_T=int,因此函数参数变为const int&amp; cint(或int的引用)上没有[0]之类的东西。

(如果您希望 c[0] 工作,因为 const int* c 工作,请记住 引用不是指针。引用是事物的“其他名称”,用于单个对象;指针指向缓冲区零个或一个或多个对象。)

当你指定的参数被称为_dummy时,_T留给编译器推导,不会犯同样的错误(传递int而不是数组类型)。

要么取出显式参数&lt;int&gt;,要么在函数参数中正确使用它(例如const T(&amp;c)[N]std::size_t非类型模板参数)。

顺便说一句,you are not permitted to use the name _T。我建议你完全去掉下划线。

【讨论】:

  • 感谢带翅膀的小行星。我对 const T(&c)[N] 有很好的直觉,但我想避免需要 N。我按照你说的做了,我删除了显式参数 。我想这会迫使编译器进行额外的扣除。你能详细说明为什么会这样吗?
  • @JeremyRoberson 这并不复杂——编译器知道数组arr 的类型,并将其与函数参数列表相匹配,为T 挑选它,然后就可以走了。就像任何其他模板参数或任何其他类型一样。但是你不能把arr 当作int,因为它不是一个。
  • 这是有道理的。谢谢
  • @JeremyRoberson 如果您觉得这个答案有帮助,请考虑接受它而不是更改问题的标题。
【解决方案2】:

对于这个模板函数

template<typename _dummy, typename _T>
void printfunc(const _T &c){
    std::cout << sizeof(c)/sizeof(c[0]) << std::endl;  //prints 5 as desired
}
int main() {

 int arr[] = {1,2,3,4,5};
 printfunc<int>(arr);
 return 0;
}

编译器从调用中提供的参数推断出第二个模板参数的类型

printfunc<int>(arr)

类型为int( &amp; )[5]

对于第二个模板函数和第三个非模板函数

template<typename T>
void printfunc(const T &c){
    std::cout << sizeof(c)/sizeof(c[0]);   //Compile Error
}

void printfunc(const int &c){
    std::cout << sizeof(c)/sizeof(c[0]);  //compile error
}

编译器发出错误,因为您在此调用中为模板函数显式指定了类型模板参数int

printfunc<int>(arr);

但使用int[5] 类型的表达式作为函数参数。或者,非模板函数需要 int 类型的左值,但您传递了 int[5] 类型的对象,该对象隐式转换为 int * 类型。此外,您不能将下标运算符用于标量整数对象

错误消息可能不同,因为在第一种情况下编译器处理模板函数,而在第二种情况下处理非模板函数。

对于非模板函数,编译器可能会在解析函数定义时发出错误,其中对 int 类型的对象使用了下标运算符。

【讨论】:

  • 啊。很简单!!随着翅膀的回答,这已经完全揭开神秘面纱了!!
猜你喜欢
  • 2018-10-14
  • 2020-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-28
相关资源
最近更新 更多