【问题标题】:Why does this template for an array's size not work? [duplicate]为什么这个数组大小的模板不起作用? [复制]
【发布时间】:2014-08-01 19:41:15
【问题描述】:

作为使用模板的一些练习,我尝试编写一个函数模板来查找数组的大小:

template <typename T>
size_t arraySize(T array[]) {
    return (sizeof(array)/sizeof(T));
}

然后我尝试使用一些不同数据类型的数组以及常规 sizeof(array)/sizeof(datatype) 计算来测试模板,如下所示:

int main(){

int arr1[20];
char arr2[20];
double arr3[20];

cout << arraySize(arr1) << ' ' << arraySize(arr2) << ' ' << arraySize(arr3) << endl;
cout << sizeof(arr1)/sizeof(int) << ' ' << sizeof(arr2)/sizeof(char) << ' ' << sizeof(arr3)/sizeof(double);

}

输出是

2 8 1
20 20 20

为什么这个模板不能按预期工作?

注意:我知道 Stack Overflow (such as this one) 上存在与模板数组大小相关的其他问题,但我主要对为什么这个特定代码不起作用感到困惑。

【问题讨论】:

  • @Koopa184 我想保留c++1y 标签,因为有一个待定的标准提案要将此函数添加到标准库。这让未来的读者更容易阅读。
  • @TemplateRex 对不起,我误会了!没关系。

标签: c++ arrays templates size c++14


【解决方案1】:

问题是T array[] 真的是T* array。要获得实际大小,您需要通过引用传递一个数组,即参数T (&amp;array)[N],其中N 是一个整数模板参数。

【讨论】:

  • T (array&amp;)[N] 在这种情况下应该是 T (&amp;array)[N] 甚至是 const T (&amp;array)[N]
  • 谢谢!您的回答促使我进一步探索指针衰减和引用。
  • @Koopa184 函数的参数列表是special case。这不是衰变,只是一种奇怪的语法。
  • @FredOverflow 是非常量数组的简单防篡改保护。当然,arraySize 函数太短太简单,不会出现这样的错误,但这并不是违反一般规则的理由:在函数体内不应该改变的函数参数应该标记为const .
  • 我发现 template&lt;class T&gt;using type=T; 使这些声明更容易:size_t arraySize(type&lt;T[N]&gt;&amp;) 对我来说比 T(&amp;)[N] 更容易阅读。
【解决方案2】:

Arrays decay to pointers 当您不传递对大小数组的引用时:

#include <cstddef>
#include <iostream>

template <typename T, std::size_t N>
size_t arraySize(T const (& array)[N]) {
    return N; // equivalent to: (sizeof(array)/sizeof(T));
}

using namespace std;

int main(){

int arr1[20];
char arr2[20];
double arr3[20];

cout << arraySize(arr1) << ' ' << arraySize(arr2) << ' ' << arraySize(arr3) << endl;
cout << sizeof(arr1)/sizeof(int) << ' ' << sizeof(arr2)/sizeof(char) << ' ' << sizeof(arr3)/sizeof(double);

}

Live Example 打印 6 次 20。

更新:目前有一个针对即将到来的 C++1y 标准的提案 N4017,该提案在标准库中提出了一个非成员 size() 函数。对于所有标准容器,这将委托给size() 成员函数,但对于原始数组,建议的实现几乎等同于我上面写的(加上constexprnoexcept):

template <class T, std::size_t N>
constexpr std::size_t size(const T (&array)[N]) noexcept
{
    return N;
}

【讨论】:

  • const T (&amp;array)[N] 在这种情况下更合适。
  • 也可以return N;.
  • @chris 当然,我只是想表明他最初的尝试可以工作,更新。
  • 请注意,N4017 的更新论文 N4280 已被 C++17 工作草案接受。
猜你喜欢
  • 1970-01-01
  • 2011-04-11
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 2011-03-23
  • 1970-01-01
  • 2015-06-10
  • 1970-01-01
相关资源
最近更新 更多