带函数模板的C ++奇怪类型转换错误

时间:2014-06-22 10:31:38

标签: c++ templates function-templates

我有这些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:\work\cpptests\cpptests\cpptests.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...

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

1 个答案:

答案 0 :(得分:3)

变量p的类型是“const int未知范围的数组”。通过C ++ 11 8.3.5,“函数”,

  

如果参数的类型包含[...]“对T未知界限数组的引用”的类型,则该程序格式不正确。

请允许我进行一些精神上的游览,了解为什么这有意义:

您可能知道即使类型T不完整,类型T *T &也是完整类型。 C ++包含一种奇怪的机制,通过该机制,变量的类型可以通过 completed 来改变。也就是说,您可以声明一个变量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 &。)

由于对未知边界数组的指针和引用具有如此有限的实用性,因此不允许它们作为函数参数类型。在您的情况下,推导出的类型恰好是“未知界限数组”类型,因此生成的程序格式不正确。