当前位置:  开发笔记 > 编程语言 > 正文

如何将数组大小作为模板传递模板类型?

如何解决《如何将数组大小作为模板传递模板类型?》经验,为你挑选了1个好方法。

当我尝试将固定大小的数组传递给模板函数时,我的编译器表现得很奇怪.代码如下:

#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并非如此.

但是,如果我将上面的函数模板的声明更改为

template 
void f(TSize (& array)[N])

问题就消失了!请注意,这里唯一的变化是从TSize Nunsigned int N.

dcl.type.simpleISO/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.



1> Johannes Sch..:

嗯,标准说14.8.2.4 / 15:

如果在具有非类型模板参数的函数模板的声明中,在函数参数列表中的表达式中使用非类型模板参数,并且如果推导出相应的模板参数,则模板 - 参数类型应与模板参数的类型完全匹配,除了从数组绑定推导出的模板参数可以是任何整数类型.

提供此示例:

template class 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

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有