使用可变参数模板函数的内置多维数组的大小

发布于 2024-12-18 07:34:23 字数 573 浏览 5 评论 0原文

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

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

在我看来,这是 ARRAY_SIZE 和类似宏的更好替代方案。

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

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

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

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

提前致谢。

In C++11 it is possible to create a function which returns the size (number of elements) of a built-in one dimensional array at compile time using constexpr. Example below:

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

This is a superior alternative to ARRAY_SIZE and similar macros imo.

However, this will only return the size of the most significant dimension of a built-in multidimensional array.

I use the following function for determining the size of a built-in two dimensional array:

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

Ideally, it would be very useful to have a function that returns the size of a built-in array with an arbitrary number of dimensions. I thought variadic templates may help but I couldn't see a way of unpacking the template paramters as only one argument is passed. Is such a function possible?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

驱逐舰岛风号 2024-12-25 07:34:23
#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;
}
#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);
}

Example:

#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;
}
热鲨 2024-12-25 07:34:23
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]); 
} 
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]); 
} 
美煞众生 2024-12-25 07:34:23

您正在寻找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 的索引是从零开始的。

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

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
    };
};

You're looking for std::extent. C++11 §20.9.5:

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

If T is not an array type, or if it has rank less than or equal to I, or if I is 0 and T has type “array of unknown bound of U”, then 0; otherwise, the bound (8.3.4) of the I’th dimension of T, where indexing of I is zero-based.

Usage, also from the Standard, prefix extent with std:: as needed:

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

You should also probably use this to replace your custom size function.

Edit: Oops, now I read to the end of the question :vP . You also need 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
    };
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文