函数模板的c++怪异类型转换错误

C++ Weird Type Conversion Error wtih Function Template

本文关键字:类型转换 错误 c++ 函数模板      更新时间:2023-10-16

我有这些c++代码:

在"header1.h"

template <typename T>
int  f1(const T& t1) {
    return 0;
}
extern const int  p[];
在cpptests.cpp

#include "header1.h"
int _tmain(int argc, _TCHAR* argv[])  {
    f1(p);
    return 0;
}

在vc++ 2010中,我得到了这个编译错误:

c:workcpptestscpptestscpptests.cpp(10): error C2664: 'f1' : cannot convert parameter 1 from 'const int []' to 'const int (&)[1]'
          Reason: cannot convert from 'const int []' to 'const int [1]'
          There is no context in which this conversion is possible
  Generating Code...

模板函数调用如何将p转换为const int (&)[1] ?

变量p的类型为" const int的未知界数组"。By c++ 118.3.5, "Functions",

如果参数的类型包含[…]引用T的未知界数组,程序是病态的。

请允许我稍微回顾一下为什么这是有意义的:

您可能知道,即使类型T是不完整的,类型T *T &也是完整类型。c++包含一种奇怪的机制,通过该机制,变量的类型可以通过完成而改变。也就是说,您可以声明具有不完整类型的变量T x;,但稍后完成变量定义中的类型。例如,取T = int[]:

extern int a[];    // `a` has incomplete type "array of unknown bound of int"
int a[10];         // now `a` has complete type "array of 10 int"

然而(参见3.9/6),假设现在我们有另一个指针类型为T *的变量:

int (*p)[] = &a;   // `p` is a pointer to an array of unknown bound

这个变量的类型已经完成了,但是它的"数组"部分永远不能完成。因此,即使a最终可能有一个完整的类型,p的类型也永远不会改变。它的类型永远不会变成int (*)[10]。这两种类型都已经完成,后者是而不是是前者的完成。

这意味着您永远不能使用 p来作为一个整体访问整个数组对象。你仍然可以通过将*p分解为指向数组第一个元素的指针来使用p(注意,*p是一个完美的左值;glvalues不需要有完整的类型,但是你永远不能通过p看到整个数组。(同样的推理也适用于T &)

由于指向未知边界数组的指针和引用的效用有限,因此不允许它们作为函数参数类型。在您的示例中,推导出的类型恰好是"未知边界的数组"类型,因此生成的程序是病态的。