泛型c++多维迭代器

Generic C++ multidimensional iterators

本文关键字:迭代器 c++ 泛型      更新时间:2023-10-16

在我当前的项目中,我正在处理多维数据结构。底层文件按顺序存储(即一个巨大的数组,而不是向量的向量)。使用这些数据结构的算法需要知道各个维度的大小。

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

目前我只是使用一个线性迭代器和一些额外的方法,返回每个维度的大小和有多少维度在第一部分。我不喜欢它的原因是我不能以合理的方式使用std:: distance(例如,只返回整个结构的距离,而不是单独返回每个维度的距离)。

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

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

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

我希望这不是太模糊或抽象。如有任何提示,我将不胜感激。

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

一旦实现完成,我将再次更新它。

我刚刚决定在Github上打开一个公共存储库:MultiDim Grid,这可能有助于满足您的需求。这是一个正在进行的项目如果你能试一下并告诉我你缺少什么/需要什么,我会很高兴的。

我已经开始在codereview这个主题上工作了。

简单点说:

MultiDim Grid提出了一个平面的单维数组多维坐标与平面之间的通用快速访问指数。

你得到了一个容器行为,所以你可以访问迭代器。

实现起来并不难。只要准确地说明你的项目需要什么功能。这是一个愚蠢的例子。

#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;
}

TODO列表:

  • 优化:尽可能使用T const&
  • 优化迭代器:预先计算realindex,然后更改realindex
  • 实现const访问器
  • ConstIterator
  • 实现operator>>operator<<序列化DimVector到/从文件