提供维度后 boost::extent 对象的类型是什么?

What is the type of a boost::extent object after providing dimensions?

说我有

#include <boost/multi_array.hpp>
using intArray3D = boost::multi_array<int, 3>;

我想创建一堆具有相同形状的 intArray3D

auto my_shape = boost::extents[3][4][5];
intArray3D xs(my_shape), ys(my_shape), zs(my_shape);

使用autoboost::extents[3][4][5]赋值给一个变量很容易,但是我如何具体找出底层类型?

documentation提到:

template gen_type<Ranges>::type

  • This type generator is used to specify the result of Ranges chained calls to extent_gen::operator[].

其中 gen_typeboost::multi_array_types::extent_gen 的成员(并且 boost::multi_array_types::extent_gen 也是全局帮助对象 boost::extents 的类型)。

您还可以看到以这种方式指定接受一组范围的构造函数(至少出于 public 文档的目的)。 For example,

namespace boost {

template <typename ValueType, 
          std::size_t NumDims, 
          typename Allocator = std::allocator<ValueType> >
class multi_array {

...

  typedef multi_array_types::extent_gen         extent_gen;

...

  explicit multi_array(extent_gen::gen_type<NumDims>::type ranges,
                       const storage_order_type& store = c_storage_order(),
                       const Allocator& alloc = Allocator());

因此,您可以在不使用 auto 的情况下重写该行代码,因为:

boost::multi_array_types::extent_gen::gen_type<3>::type my_shape =
    boost::extents[3][4][5];

这对于局部变量来说有点傻,但也许您想将一组范围存储在 class 或类似的东西中。如果是这样的话,按照官方文档的接口就是这样操作的。

(如评论中所述,此 typedef 解析为的实际类型涉及 boost::internal::,但您永远不应在代码中使用“内部”命名空间中的任何内容,因为这在未来版本中可能会发生变化.)

我会存储一个

template<class T>
using factory=std::function< T() >;

然后当我想创建很多数组时:

auto my_shape = boost::extents[3][4][5];
factory<intArray3D> shaper = [my_shape]{ return intArray3D(my_shape); };
intArray3D xs(shaper()), ys(shaper()), zs(shaper());

这消除了对提升范围的确切类型的依赖。

最重要的是,

  1. 你不必知道
  2. 你也不必使用 extents

很多东西只要满足documented criteria:

就可以接受

集合概念记录在 that link

Live On Coliru

#include <boost/multi_array.hpp>
#include <iostream>
using intArray3D = boost::multi_array<int, 3>;

void dump_shape(intArray3D const& arr) {
    for (unsigned dim = 0; dim < arr.dimensionality; ++dim)
        std::cout << arr.shape()[dim] << " ";
    std::cout << "\n";
}

int main() {
    {
        auto my_shape = boost::extents[3][4][5];
        intArray3D xs(my_shape), ys(my_shape), zs(my_shape);
        dump_shape(xs); dump_shape(ys); dump_shape(zs);
    }

    {
        std::array<int, 3> my_shape { 3, 4, 5 };
        intArray3D xs(my_shape), ys(my_shape), zs(my_shape);
        dump_shape(xs); dump_shape(ys); dump_shape(zs);
    }

    {
        std::vector<int> my_shape { 3, 4, 5 };
        intArray3D xs(my_shape), ys(my_shape), zs(my_shape);
        dump_shape(xs); dump_shape(ys); dump_shape(zs);
    }

}

版画

3 4 5 
3 4 5 
3 4 5 
3 4 5 
3 4 5 
3 4 5 
3 4 5 
3 4 5 
3 4 5