4

在 C++11 中,可以创建一个函数,该函数在编译时使用 constexpr 返回内置一维数组的大小(元素数)。下面的例子:

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

这是 ARRAY_SIZE 和类似的宏 imo 的绝佳替代品。

但是,这只会返回内置多维数组的最重要维度的大小。

我使用以下函数来确定内置二维数组的大小:

template <typename T, std::size_t N, std::size_t N2>
constexpr std::size_t size(T (&array)[N][N2])
{
     return N * N2;
}

理想情况下,拥有一个返回具有任意维数的内置数组大小的函数会非常有用。我认为可变参数模板可能会有所帮助,但由于只传递了一个参数,因此我看不到解包模板参数的方法。这样的功能可能吗?

提前致谢。

4

3 回答 3

5
#include <type_traits>
#include <cstdlib>

template <typename T>
constexpr size_t size(const T&) noexcept
{
    return sizeof(T)/sizeof(typename std::remove_all_extents<T>::type);
}

例子:

#include <cstdio>
int main()
{
    int a[3][4][7][12];
    char f[6];

    printf("%lu == %ld ?\n", size(a), 3*4*7*12);
    printf("%lu == %ld ?\n", size(f), 6);

    return 0;
}
于 2011-11-28T18:30:33.387 回答
3
template<typename T> constexpr int size(T const&) { 
  return 1; 
}

template<typename T, int N> constexpr int size(T const (&a)[N]) { 
  return N * size(a[0]); 
} 
于 2011-11-28T19:53:12.987 回答
2

你正在寻找std::extent. C++11 §20.9.5:

template <class T, unsigned I = 0> struct extent;

如果 T 不是数组类型,或者它的秩小于或等于 I,或者如果 I 为 0 并且 T 的类型为“U 的未知边界数组”,则为 0;否则,T 的第 I 维的界限 (8.3.4),其中 I 的索引是从零开始的。

extent用法,也来自标准,根据需要加上前缀std::

assert((extent<int[2][4], 1>::value) == 4);

您还应该使用它来替换您的自定义size函数。

编辑:哎呀,现在我读到问题的结尾:vP。你还需要std::remove_extent.

template< typename multi_array, bool = std::is_array< multi_array >::value >
struct total_extent;

template< typename multi_array >
struct total_extent< multi_array, false > {
    enum { value = 1 };
};

template< typename multi_array >
struct total_extent< multi_array, true > {
    enum {
        value = std::extent< multi_array >::value
              * total_extent< typename std::remove_extent< multi_array >
                              ::type >::value
    };
};
于 2011-11-28T15:54:35.690 回答