微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 std::extent 获取多维数组中元素的总数

如何解决使用 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);

所以使用remove_all_extents

在模板版本中(如在 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 举报,一经查实,本站将立刻删除。