如何查找多维 std::array 的大小?

3
我有一个多维的std::array,正在寻找适当的(方便和高效)方法来查找其大小(以单元格数或字节为单位)。 size()仅返回最后一维的大小(这是可以理解的)。
std::array<std::array<std::array<std::array<double, 2>, 3>, 6>, 100> my_array;

my_array.size();  // returns 100

尽管在编译时知道数组的大小,但我希望避免使用#define SIZE_OF_MY_ARRAY或全局变量,因为我正在寻找一种比传递数组大小更好的方法(就像“旧”数组中那样,而不是std数组),或者告诉其他人使用定义的术语。
我也不想每次都计算它。
也许这两个偏好对于多维数组来说是不可能的?
我如何有效地找到my_array的总大小?我正在使用

my_array.size() * my_array[0].size() * my_array[0][0].size() * my_array[0][0][0].size() 怎么样? - Blaze
以字节为单位的大小是 sizeof(my_array),以单元格为单位的大小是 my_array.size(),双精度浮点数的数量是 sizeof(my_array) / sizeof(double) - user7860670
说实话,我不明白这个问题。如果你在编译时知道所有数组的大小,为什么不能简单地将它们相乘,即 size = 2 * 3 * 6 * 100; - vahancho
“std::array” 的设计理念不就是“光头”吗(没有多余的信息,就像内置数组一样),即 sizeof(my_array)/sizeof(double) 可以得到元素数量吗? - Peter - Reinstate Monica
@vahancho 我敢打赌,因为OP正在寻找一种不涉及特定索引或维数数量的解决方案。 - Peter - Reinstate Monica
感谢大家的评论。我编辑了问题,回答了一些你们写的内容,也为将来发现这个问题的其他人做了一些修改。 - Micha
5个回答

3

编写一个在编译时计算此内容的小型实用程序并不太困难。

template<typename T> struct arr_sz {
    static constexpr std::size_t size = sizeof(T);
};

template<typename T, std::size_t N>
struct arr_sz<std::array<T, N>> {
    static constexpr std::size_t size = N * arr_sz<T>::size;
};

以上内容应该可以解开任何实用深度的嵌套数组定义,并计算出存储 T 的字节数,其中排除所有可能的填充。

使用它的一个例子是:

std::array<std::array<std::array<std::array<double, 2>, 3>, 6>, 100> my_array;
constexpr auto sz = arr_sz<decltype(my_array)>::size;
static_assert(sz == sizeof(double) * 2 * 3 * 6 * 100, ""); 

希望您可以观看实时演示


arr_sz<decltype(my_array)>::size / sizeof(arr_sz<decltype(my_array)>::value_type) 的结果是否可能大于数组元素总数? - Peter - Reinstate Monica
@PeterA.Schneider - 如果在计算过程中发生了无符号溢出,它可能会更小。我不知道它怎么会更大。 - StoryTeller - Unslander Monica

3
你可以使用递归来计算其大小:

你可以使用递归来计算文件夹的大小:

template<typename T>
size_t get_array_full_size(T &val) { // for the last array type (double in this case)
    return 1;
}

template<typename T, size_t Len>
size_t get_array_full_size(std::array<T, Len> &arr) {
    return get_array_full_size(arr[0]) * arr.size();
}

int main() {
    std::array<std::array<std::array<std::array<double, 2>, 3>, 6>, 100> my_array;
    std::cout << get_array_full_size(my_array) << std::endl;
    return 0;
}

有趣。这种函数式方法似乎类似于StoryTeller的数据方法。 - Peter - Reinstate Monica

2

How about

sizeof(my_array)/sizeof(double);

问题可能是标准是否保证了这一点。 - Peter - Reinstate Monica
2
@PeterA.Schneider 看起来并不是这样的:https://dev59.com/p18e5IYBdhLWcg3w-OUn - Dan M.

2

类似于 @KorelK 的方法。递归模板函数将在 std::array 是基本类型 的类模板中停止。

(在线查看)

#include <array>
#include <type_traits> // std::is_fundamental_v

template<typename Type, std::size_t N>
std::size_t overall_size(const std::array<Type, N>&)
{
    if constexpr(std::is_fundamental_v<Type>)   return N;
    else return N * overall_size(Type{});
}

1
你可以使用 constexpr 变量绑定尺寸,然后使用这些变量计算所需的数量。
constexpr int n1 = 2;
constexpr int n2 = 3;
constexpr int n3 = 6;
constexpr int n4 = 100;

std::array<std::array<std::array<std::array<double, n1>, n2>, n3>, n4> my_array;

constexpr int myArraySize = n1*n2*n3*n4;

1
我想OP想要从数组中提取常量并找到一个通用解决方案,例如可以编写为模板函数,适用于所有std :: array,而不管它们的特定大小或维数。您的解决方案还将替换size()成员函数,该函数显然很有用,但仅适用于最后一维。 - Peter - Reinstate Monica
@PeterA.Schneider 公正的观点。我认为StoryTeller刚刚发布了这样的解决方案,它确实更优秀。 - lubgr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接