作为函数的C阵列的大小

Size-Of C-Array as a function?

本文关键字:阵列 函数      更新时间:2023-10-16

可能重复:
这是如何";阵列大小";模板功能工作?

有没有可能在C++(C++0x(中实现没有宏的NARR

const static pair<string,int> data[] = {
    {"Montag",1}, {"Dienstag",2}, {"Mittwoch",3}, {"Donnerstag",4},
    {"Freitag",5}, {"Samstag",6}, {"Sonntag",7}
};
#define NARR(A) (sizeof(A)/sizeof(*A))
const static map<string,int> german_weekdays(data, data+NARR(data));

一个简单的函数是不可能的,因为[]失去了它的大小信息,变成了另一个点:

size_t narr(sometype arr[]) { /* won't work */ }

模板?超载?魔术

这在C++中是可能的:

template< typename T, std::size_t Size >
std::size_t size(const T (&)[Size])
{
  return Size;
}

与宏解决方案相比,这种方法的优点是,如果您试图将指针传递给它,编译器会发出一条严重的错误消息。

在C++0x:中

#include <iterator>
const static map<string,int> german_weekdays(data, std::end(data));

如果您愿意,也可以使用std::begin(data),用于对称性或泛型[*]。而且可能你可以使用一个初始值设定项列表而不是数组。。。

[*]尽管对于完整的泛型,您可能应该这样做:

using std::begin;
using std::end;
begin(data), end(data);

原因是新的"基于范围的循环"语法相当于在没有限定的情况下使用beginend,但使用std作为ADL的关联命名空间。与std::swap一样,类型的作者可能会提供beginend函数,这些函数旨在通过ADL找到。它们可能应该提供begin()end()成员函数,std::beginstd::end将调用这些函数。但是,如果他们提供了适用于基于范围的,而不适用于您的代码的东西,那么您将不得不争论谁应该更改。

我现在不能测试这个,因为我离开了一段时间,最新的GCC 4.6刚刚拒绝编译,但constexpr应该会很快解决这个问题。当然,最好用史蒂夫的建议来回避这个问题。

template< typename T, size_t N >
constexpr size_t narr( T const (&)[ N ] )
    { return N; }