通用C ++多维迭代器

时间:2015-07-16 08:44:38

标签: c++ algorithm multidimensional-array iterator

在我目前的项目中,我正在处理多维数据结构。 基础文件是顺序存储的(即一个巨大的数组,没有矢量矢量)。 使用这些数据结构的算法需要知道各个维度的大小。

我想知道一个多维迭代器类是否已经以通用的方式在某处定义,并且是否有任何标准或首选方法来解决这个问题。

目前我只是使用线性迭代器和一些额外的方法来返回每个维度的大小以及第一部分中有多少维度。我不喜欢它的原因是因为我不能以合理的方式使用std :: distance(即只返回整个结构的距离,但不是分别针对每个维度)。

在大多数情况下,我将以线性方式访问数据结构(第一个维度从头到尾 - >下一个维度+ ......等等),但最好知道一个维度"何时结束& #34 ;.在这种方法中,我不知道如何使用operator *(),operator +()和operator ==()来做到这一点。

矢量方法的方法是不受欢迎的,因为我不想分割文件。此外,算法必须在具有不同维度的结构上运行,因此难以概括(或者可能有一种方法?)。

Boost multi_array具有相同的问题(多个"级别"迭代器)。

我希望这不是太模糊或抽象。任何正确方向的暗示都会受到赞赏。

我一直在寻找解决方案,并重新访问了boost :: multi_array。事实证明,可以使用它们生成关于数据的子视图,但同时也可以在顶层采用直接迭代器并且隐含地“平坦化”#34;数据结构。然而,multi_array的实现版本不适合我的需要,因此我可能会自己实现一个(在后台处理文件的缓存),与其他multiararrays兼容。

完成实施后,我会再次更新它。

2 个答案:

答案 0 :(得分:2)

我刚刚决定在Github上开设一个公共存储库:MultiDim Grid这可能对您的需求有所帮助。这是一个正在进行的项目 如果你能尝试并告诉我你错过/需要什么,我会很高兴的。

我已经开始使用代码视图上的topic来处理此问题。

简单地说:

  

MultiDim Grid提出了一个平面的单维数组,它提供了一个   多维坐标和展平之间的通用快速访问   索引。

您获得了容器行为,因此您可以访问迭代器。

答案 1 :(得分:1)

这并不难实现。只需准确说明项目所需的功能。这是一个愚蠢的样本。

threadId

TODO清单:

  • 优化:尽可能使用#include <iostream> #include <array> #include <vector> #include <cassert> template<typename T, int dim> class DimVector : public std::vector<T> { public: DimVector() { clear(); } void clear() { for (auto& i : _sizes) i = 0; std::vector<T>::clear(); } template<class ... Types> void resize(Types ... args) { std::array<int, dim> new_sizes = { args ... }; resize(new_sizes); } void resize(std::array<int, dim> new_sizes) { clear(); for (int i = 0; i < dim; ++i) if (new_sizes[i] == 0) return; _sizes = new_sizes; int realsize = _sizes[0]; for (int i = 1; i < dim; ++i) realsize *= _sizes[i]; std::vector<T>::resize(static_cast<size_t>(realsize)); } decltype(auto) operator()(std::array<int, dim> pos) { // check indexes and compute original index size_t index; for (int i = 0; i < dim; ++i) { assert(0 <= pos[i] && pos[i] < _sizes[i]); index = (i == 0) ? pos[i] : (index * _sizes[i] + pos[i]); } return std::vector<T>::at(index); } template<class ... Types> decltype(auto) at(Types ... args) { std::array<int, dim> pos = { args ... }; return (*this)(pos); } int size(int d) const { return _sizes[d]; } class Iterator { public: T& operator*() const; T* operator->() const; bool operator!=(const Iterator& other) const { if (&_vec != &other._vec) return true; for (int i = 0; i < dim; ++i) if (_pos[i] != other._pos[i]) return true; return false; } int get_dim(int d) const { assert(0 <= d && d < dim); return _pos[d]; } void add_dim(int d, int value = 1) { assert(0 <= d && d < dim); _pos[d] += value; assert(0 <= _pos[i] && _pos[i] < _vec._sizes[i]); } private: DimVector &_vec; std::array<int, dim> _pos; Iterator(DimVector& vec, std::array<int, dim> pos) : _vec(vec), _pos(pos) { } }; Iterator getIterator(int pos[dim]) { return Iterator(*this, pos); } private: std::array<int, dim> _sizes; }; template<typename T, int dim> inline T& DimVector<T, dim>::Iterator::operator*() const { return _vec(_pos); } template<typename T, int dim> inline T* DimVector<T, dim>::Iterator::operator->() const { return &_vec(_pos); } using namespace std; int main() { DimVector<int, 4> v; v.resize(1, 2, 3, 4); v.at(0, 0, 0, 1) = 1; v.at(0, 1, 0, 0) = 1; for (int w = 0; w < v.size(0); ++w) { for (int z = 0; z < v.size(1); ++z) { for (int y = 0; y < v.size(2); ++y) { for (int x = 0; x < v.size(3); ++x) { cout << v.at(w, z, y, x) << ' '; } cout << endl; } cout << "----------------------------------" << endl; } cout << "==================================" << endl; } return 0; }
  • 优化迭代器:预先计算realindex,然后只需更改该realindex
  • 实施T const&访问者
  • 实施const
  • 实施ConstIteratoroperator>>将DimVector序列化为文件