当我尝试将固定大小的数组传递给模板函数时,我的编译器表现得很奇怪.代码如下:
#include#include #include template void f(TSize (& array)[N]) { std::copy(array, array + N, std::ostream_iterator (std::cout, " ")); std::cout << std::endl; } int main() { int x[] = { 1, 2, 3, 4, 5 }; unsigned int y[] = { 1, 2, 3, 4, 5 }; f(x); f(y); //line 15 (see the error message) }
它在GCC 4.1.2中产生以下编译错误:
test.cpp|15| error: size of array has non-integral type ‘TSize’ test.cpp|15| error: invalid initialization of reference of type ‘unsigned int (&)[1]’ from expression of type ‘unsigned int [5]’ test.cpp|6| error: in passing argument 1 of ‘void f(TSize (&)[N]) [with TSize = unsigned int, TSize N = ((TSize)5)]’
请注意,第一个调用编译并成功.这似乎意味着虽然int
是不可或缺的,但事实unsigned int
并非如此.
但是,如果我将上面的函数模板的声明更改为
templatevoid f(TSize (& array)[N])
问题就消失了!请注意,这里唯一的变化是从TSize N
到unsigned int N
.
dcl.type.simple
ISO/IEC FDIS 14882:1998最终草案中的[ ] 节似乎暗示"整体类型"是签名或未签名:
在
signed
符力char
对象,并签署位字段; 它与其他整数类型是多余的.
关于固定大小的数组声明,草案说[ dcl.array
]:
如果存在constant-expression(
expr.const
),则它应是一个整数常量表达式,其值应大于零.
那么为什么我的代码使用显式unsigned
大小类型,使用推断的signed
大小类型但不使用推断的unsigned
大小类型?
编辑 Serge想要知道我需要第一个版本的位置.首先,这个代码示例显然是简化的.我的真实代码更精细一些.该数组实际上是另一个数组中的索引/偏移数组.因此,从逻辑上讲,数组的类型应与其大小类型相同,以获得最大的正确性.否则,我可能会遇到类型不匹配(例如,在unsigned int
和之间std::size_t
).不可否认,这在实践中不应成为问题,因为编译器会隐式转换为两种类型中较大的一种.
编辑2我站得更正(谢谢,litb):大小和偏移当然是逻辑上不同的类型,特别是C阵列的偏移是类型std::ptrdiff_t
.
嗯,标准说14.8.2.4 / 15
:
如果在具有非类型模板参数的函数模板的声明中,在函数参数列表中的表达式中使用非类型模板参数,并且如果推导出相应的模板参数,则模板 - 参数类型应与模板参数的类型完全匹配,除了从数组绑定推导出的模板参数可以是任何整数类型.
提供此示例:
templateclass A { /* ... */ }; template void f(A ); void k1() { A<1> a; f(a); // error: deduction fails for conversion from int to short f<1>(a); // OK }
这表明无法编译代码的编译器(显然是GCC和Digital Mars)做错了.我用Comeau测试了代码,它编译好你的代码.我认为非类型模板参数的类型是否取决于type-parameter的类型是否有所不同.14.8.2.4/2
表示模板参数应该相互独立推导,然后组合成函数参数的类型.结合/ 15,它允许维度的类型具有不同的整数类型,我认为你的代码都很好.一如既往,我采取c ++ - 很复杂 - 所以我可能是错误的卡:)
更新:我已经查看了GCC中的通道,它会发出错误消息:
... type = TREE_TYPE (size); /* The array bound must be an integer type. */ if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type)) { if (name) error ("size of array %qD has non-integral type %qT", name, type); else error ("size of array has non-integral type %qT", type); size = integer_one_node; type = TREE_TYPE (size); } ...
它似乎错过了将大小的类型标记为依赖于早期代码块.由于该类型是模板参数,因此它是依赖类型(请参阅参考资料14.6.2.1
).
更新: GCC开发人员修复了它:Bug#38950