如何解决使用 std::extent 获取多维数组中元素的总数
如何使用 std::extent 查找多维数组中的元素总数。这是我的示例代码:
#include <iostream>
#include <type_traits>
int main()
{
int32_t int_arr[10][100][1000];
int32_t no_of_elements = 1;
// compiler error in below for loop block
for (int32_t i = 0; i < std::rank<decltype(int_arr)>{}; ++i)
no_of_elements *= std::extent<decltype(int_arr),i>{};
no_of_elements *= std::extent<decltype(int_arr),0>{};
no_of_elements *= std::extent<decltype(int_arr),1>{};
no_of_elements *= std::extent<decltype(int_arr),2>{};
std::cout << no_of_elements << std::endl;
std::cout << sizeof(int_arr) / sizeof(std::remove_all_extents<decltype(int_arr)>::type) << std::endl;
return 0;
}
error: the value of ‘i’ is not usable in a constant expression 9 | no_of_elements *= std::extent<decltype(int_arr),i>{};
解决方法
更简单的方法是获取数组元素的类型,然后 sizeof(array)/sizeof(element)
是一个答案:
int32_t int_arr[10][100][1000];
using element = std::remove_all_extents<decltype(int_arr)>::type;
no_of_elements = sizeof(int_arr)/sizeof(element);
在模板版本中(如在 C++14 变量模板中):
template <typename ArrayType>
constexpr std::size_t no_of_elements_v =
sizeof(ArrayType) / sizeof(remove_all_extents_t<ArrayType>;
如果您真的坚持使用 C++11 和 std::extent - 这就是解决方案:
template <typename T,std::size_t rank = std::rank<T>{},std::size_t dim = 0>
struct NumOfElements :
std::integral_constant<std::size_t,std::extent<T,dim>{} * NumOfElements<T,rank,dim + 1>::value>
{};
template <typename T,std::size_t rank>
struct NumOfElements<T,rank> :
std::integral_constant<std::size_t,1u>
{};
并使用 NumOfElements<decltype(int_arr)>::value
但是这个简单的模板版本要简单得多,没有任何 type_traits,如果你用简单的静态成员变量替换 integer_constant - 它甚至应该在 C++11 之前的版本中工作:
template <typename T>
struct NumOfElements : std::integral_constant<std::size_t,1u>
{};
template <typename T,std::size_t N>
struct NumOfElements<T[N]> : std::integral_constant<std::size_t,N * NumOfElements<T>::value>
{};
,
使用 C++14 std::index_sequence
,您可以将 std::extent
用于以下内容:
template <typename T,std::size_t... Is>
constexpr std::size_t count_elements(std::index_sequence<Is...>)
{
return (1 * ... * std::extent<T,Is>{}); // C++17 fold expression
// Alternatives exist for C++11/C++14
}
template <typename T>
constexpr std::size_t count_elements()
{
return count_elements<T>(std::make_index_sequence<std::rank<T>{}>());
}
int main()
{
int32_t int_arr[10][100][1000];
int32_t no_of_elements = count_element<decltype(int_arr)>();
std::cout << no_of_elements << std::endl;
}
,
#include <iostream>
#include <type_traits>
#include <typeinfo>
template<class A>
size_t getSize(const A&)
{
typedef typename std::remove_all_extents<A>::type Type;
return sizeof(A) / sizeof(Type);
}
int main()
{
int a1[3][10];
float a2[5][10][10];
double a3[3][10];
std::int32_t int_arr[10][100][1000];
std::cout << "Size of array a1: " << getSize(a1) << std::endl;
std::cout << "Size of array a2: " << getSize(a2) << std::endl;
std::cout << "Size of array a3: " << getSize(a3) << std::endl;
std::cout << "Size of array int_arr: " << getSize(int_arr) << std::endl;
}
输出:
Size of array a1: 30
Size of array a2: 500
Size of array a3: 30
Size of array int_arr: 1000000
此代码的一个缺点是为每种类型的数组生成函数 getSize():
type of a1: int[3][10] (GCC outputs: A3_A10_i)
type of a2: float[5][10][10] (GCC outputs: A5_A10_A10_f)
type of a3: double[3][10] (GCC outputs: A3_A10_d)
,
我不认为 std::extent
是这里的正确选择。我只是定义一个“递归”模板:
template<typename T>
struct nested_array_size
{
static constexpr size_t value = 1;
};
template<typename T,size_t N>
struct nested_array_size<T[N]>
{
static constexpr size_t value = N * nested_array_size<T>::value;
};
std::cout << nested_array_size<double[1][2][3][4]>::value << std::endl;
std::cout << nested_array_size<int[5]>::value << std::endl;
std::cout << nested_array_size<int[5][6]>::value << std::endl;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。