C ++实现自定义矩阵类迭代器 [英] c++ implementing iterators for custom matrix class
问题描述
我目前工作的一个线性代数库(自定义向量和矩阵加上一些算法)用于教育目的和个人使用。我试图执行一个列迭代器,遍历矩阵的指定列的迭代器。
I am currently working on a linear algebra library (custom vector and matrix plus some algorithms) for educational purposes and personal use. I tried to implement a column iterator, an iterator that traverses a specified column of a Matrix.
下面是向量类的code样品(赖以矩阵类是建立在):
Here is a code sample of the vector class (upon which the matrix class is built on):
template<class T>
class MVector
{
std::vector<T> data;
public:
explicit MVector(const std::size_t& n) :data(n) {}
explicit MVector(std::size_t&& n) :data(n) {}
typename std::vector<T>::iterator Begin(){
return data.begin();
}
typename std::vector<T>::iterator End(){
return data.end();
}
// many more functions and overloaded operators
// end of class
};
Matrix类是基于这个载体(或性病::向量为这件事),看起来像:
The matrix class is based on this vector (or the std::vector for this matter), and looks like:
template<class T, std::size_t rowsize, std::size_t colsize>
class Matrix
{
private:
// Data is stored in a MVector, a modified std::vector
MVector<T> matrix;
// size of row dimension of the matrix
std::size_t row_dim;
// size of row dimension of the matrix
std::size_t column_dim;
public:
Matrix(std::initializer_list<T> il) :matrix(il),
row_dim(rowsize), column_dim(colsize){}
//other constructors...
// iterator
typename std::vector<T>::iterator Begin(std::size_t row = 0){
return matrix.Begin()+index(row,0);
}
typename std::vector<T>::iterator End(std::size_t row = rowsize){
return matrix.Begin()+index(row,0);
// index (convenience) function to access elements of the matrix via some_matrix(i,j)
std::size_t index(std::size_t r, std::size_t c) const {
return r*cols()+c;
}
// this is exactly what I want the iterator to do:
// only without creating and returning an object.
// get c'th column
// slicing is possible from both ends and by "jumping" over elements
// @ param "begin" - starts at the n'th element
// @ param "end" - subtracts m from from the last element.
// @ param "by" - selects every n'th column
MVector<T> get_column(std::size_t c, std::size_t begin = 0,
std::size_t end = 0, std::size_t by = 1) const{
assert(c < cols() && end < rows());
MVector<T> columns;
for (std::size_t i = index(begin, c); i < index(rows()-end,c); i+=by*cols()) {
columns.addTo(matrix[i]);
}
return columns;
}
// end of class
};
所以,迭代行正常工作都是我要做的是:
So, iterating the rows works fine all I have to do is:
int main{
Matrix<int, 3, 2> a = {1,2,3,4,5,6};
for (std::vector<int>::iterator iter = a.Begin(1); iter != a.End(2); iter++) {
std::cout << *iter << " ";
}
std::cout << endl;
return 0;
}
bash-3.2$ ./main
3 4
这正是我想要的。然而遍历列不与方法工作。因此,我寻找其他的解决方案,并发现这个设计迭代的Matrix类文章这听起来非常相似,我的问题和情况,但是我不能推断一个解决问题的办法。
which is exactly what I want. However traversing the columns does not work with that approach. Hence I look for other solutions and found this Designing iterators for a Matrix class article which sounds very similar to my problem and situation, however I could not deduce a solution to the problem.
其他建议指出Boost库迭代器:特别是:
Other suggestions pointed to the boost libraries iterators: in particular to:
boost::adaptors::stride(rng, n)
boost::adaptors::slice(rng, n, m)
根据需要这的确提供非常相似的结果。但这样做我get_column功能。不过,我不希望创建一个新的对象。这就是升压功能做的。从文档返回:一个新的系列基于其中n的步骤进行遍历RNG。
which indeed provide very similar results as desired. But so does my get_column function. However I do not want to create a new object. Which is what the boost functions do. From the documentation "Returns: A new range based on rng where traversal is performed in steps of n."
如此看来,迭代器不知道什么时候停止。
So it seems that the iterator does not know when to stop.
所以,我回到了原点:如何返回时迭代器,通过存储为载体的矩阵的列迭代
So I am back at square one: how to return am iterator that iterates through the columns of a Matrix that is stored as a vector?
推荐答案
我找到了一个解决问题的办法。它的组合:
I found a solution to the problem. It's a combination of:
本:获取迭代器区间的每个第n个元素
这:<一href=\"http://www.$c$cproject.com/Questions/331444/How-to-use-boost-filter-iterator-as-a-class-member\" rel=\"nofollow\">http://www.$c$cproject.com/Questions/331444/How-to-use-boost-filter-iterator-as-a-class-member
在尽头,有助推周围没有办法。该解决方案是非常简单的,看起来像:
In the end, there was no way around boost. The solution is very simple and looks like:
template<class U>
struct EveryNth {
bool operator()(const U& ) { return m_count++ % N == 0; }
EveryNth(std::size_t i) : m_count(0), N(i) {}
private:
int m_count;
std::size_t N;
};
class Matrix{
// code here
typedef boost::filter_iterator<EveryNth<T>,
typename std::vector<T>::iterator> FilterIter;
FilterIter begin_jump(std::size_t i){
return boost::make_filter_iterator<EveryNth<T> >(EveryNth<T>(i), data.begin(), data.end());
}
FilterIter end_jump(std::size_t i){
return boost::make_filter_iterator<EveryNth<T> >(EveryNth<T>(i), data.end(), data.end());
}
};
和主要的:
int main(int argc, char *argv[]){
std::vector<int> b = {1,2,3,4,5,6,7,8,9};
MVector<int> a = MVector<int>(b);
for_each(a.begin_jump(2), a.end_jump(2),
[](int i){std::cout << i << " " ;}
);
std::cout << std::endl;
return 0;
}
bash-3.2$ ./main
1 3 5 7 9
或使用a.begin_jump(3),而不是两个
or using a.begin_jump(3) instead of two:
bash-3.2$ ./main
1 4 7
,这正是预期的结果。
which is exactly the intended result.
这篇关于C ++实现自定义矩阵类迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!