通用C ++多维迭代器 [英] Generic C++ multidimensional iterators

查看:158
本文介绍了通用C ++多维迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In my current project I am dealing with a multidimensional datastructure. The underlying file is stored sequentially (i.e. one huge array, no vector of vectors). The algorithms that use these datastructures need to know the size of the individual dimensions.

我想知道一个多维迭代器类是否在一个通用的如果有任何标准或首选方法如何解决这个问题。

I am wondering if a multidimensional iterator class has been definied somewhere in a generic way and if there are any standards or preferred ways on how to tackle this.

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

At the moment I am just using a linear iterator with some additional methods that return the size of each dimension and how many dimensions are there in the first part. The reason I don't like it is because I can't use std:: distance in a reasonable way for example (i.e. only returns distance of the whole structure, but not for each dimension separately).

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

For the most part I will access the datastructure in a linear fashion (first dimension start to finish -> next dimension+...and so on), but it would be good to know when one dimension "ends". I don't know how to do this with just operator*(), operator+() and operator==() in such an approach.

是不受欢迎的,因为我不想拆分文件。另外,算法必须对具有不同维度的结构进行操作,因此难以推广(或者可能有一种方法?)。

A vector of vectors approach is disfavored, because I don't want to split up the file. Also the algorithms must operate on structure with different dimensionality and are therefore hard to generalize (or maybe there is a way?).

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

Boost multi_array has the same problems (multiple "levels" of iterators).

我希望这不是太模糊或抽象。

I hope this is not too vague or abstract. Any hint in the right direction would be appreciated.

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

I was looking for a solution myself again and revisited boost:: multi_array. As it turns out it is possible to generate sub views on the data with them, but at the same time also take a direct iterator at the top level and implicitely "flatten" the data structure. The implemented versions of multi_array however do not suit my needs, therefore I probably will implement one myself (that handles the caching of the files in the background) that is compatible with the other multi_arrays.

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

I will update it again once the implementation is done.

推荐答案

这不难实现。只需说明你的项目需要什么功能。这是一个蠢的样本。

That's not that difficult to implement. Just state precisely what functionality your project requires. Here's a dumb sample.

#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列表:


  • optimize:如果可能,使用 T const&

  • optimizate iterator:precompute realindex,

  • 实现 ConstIterator
  • code>
  • 实施 operator>> 运算符<< 将/ />文件中的DimVector序列化到

  • optimize: use T const& when possible
  • optimizate iterator: precompute realindex and then just change that realindex
  • implement const accessors
  • implement ConstIterator
  • implement operator>> and operator<< to serialize DimVector to/from file

这篇关于通用C ++多维迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆