泛型c++多维迭代器
Generic C++ multidimensional iterators
在我当前的项目中,我正在处理多维数据结构。底层文件按顺序存储(即一个巨大的数组,而不是向量的向量)。使用这些数据结构的算法需要知道各个维度的大小。
我想知道多维迭代器类是否已经在某个地方以通用的方式定义,如果有任何标准或首选的方法来解决这个问题。
目前我只是使用一个线性迭代器和一些额外的方法,返回每个维度的大小和有多少维度在第一部分。我不喜欢它的原因是我不能以合理的方式使用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
访问器 - 实现
operator>>
和operator<<
序列化DimVector到/从文件
ConstIterator
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 对于set上的循环-获取next元素迭代器
- 为什么output_editor Concept不需要output_e迭代器标记
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- std::vector::迭代器是否可以合法地作为指针
- 跟随整数索引列表的自定义类迭代器
- 不明白迭代器,引用和指针失效,一个例子
- 我可以使用反向迭代器作为ForwardIt吗
- ESP8266单片机矢量迭代器的C++问题
- 如何在C++中将迭代器作为函数参数传递
- 是否应避免从非常量迭代器转换为常量迭代器?
- 如何在 c++ 中将字符串迭代器变量传递给函数?
- 为什么 vector 的随机访问迭代器给出与指针不同的内存地址?
- 为什么 C++ std::unordered_map 从 emplace/ 找到返回一个迭代器?