为Matrix类设计迭代器 [英] Designing iterators for a Matrix class

查看:140
本文介绍了为Matrix类设计迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个 Matrix< T> 类。在实现迭代器时,我遇到了一个设计难题。



在内部,矩阵将数据保存在 std :: vector< T& / code>(row-major)。

迭代矩阵的一种方法是通过double迭代器(嵌套)(由 row_double template parameter):

  for(auto it_i = mat.Begin< row_double>(); it_i< mat.End< row_double>(); ++ it_i){
for(auto it_j = it_i-> Begin(); it_j< it_i-> End(); ++ it_j){
cout< < * it_j<< ;
}
cout<< endl;
}

第一个迭代器 Matrix< T> :: Iterator< ; row_double>




  • 遍历矩阵的行

  • RowProxy 成员

  • 解除引用返回 RowProxy li>


RowProxy 返回 std :: vector< T> ;: :iterator 迭代器通过 Begin() End() >

我的想法是为 RowProxy 知道行的开始和行的大小(矩阵列的数量)

$ <$ p $ <$>

/ p>


  • 我的第一种方法是让行的开头是 std :: vector< T& :iterator

    问题是在Visual Studio中迭代器知道向量,并且有迭代器算法的调试检查。当构造 ReverseEnd 迭代器(对于第一行之前的行)时,它抛出一个错误:行的开头是 num_columns 之前的向量开始。 请注意,这与取消引用无关(whitch是UB)。我不能创建迭代器。


  • 我的第二种方法是让行的开始是一个原始指针 T *

    这里的问题是 LineProxy 需要返回 std :: vector< T> :: iterator (通过它自己的 Begin 等),我不能(不知道如何) std :: vector< T> :: iterator 以标准方式从 T * (没有找到任何特定于 std :: vector< T> :: iterator 的参考,只是迭代器概念。在visual Studio中似乎有一个构造函数<$ c $在gcc a (T *)中没有一个在另一个中起作用(例如,c>(T *,std :: vector *)




我现在看到的解决方案是让我自己的迭代器与 std :: vector< T> :: iterator 但是不绑定到任何向量,并且可以从 T * 并使 RowProxy 返回。



由于这是库的一部分(代码位于头文件中),编译器选项是不可能的(包括宏控制编译器选项,因为它们修改包含头的程序的整个行为,而不仅仅是库代码的行为)。此外,解决方案必须符合标准。语言是 C ++ 11

解决方案

做这个如上所述是使用Eigen,它是一个非常好的包。下一个最简单的事情就是在你的类中存储大小信息,然后你有一个非常好的方法从你的矩阵中获取一个特定的元素。只需写一个返回向量[i + j * rowlength]的(i,j)运算符。迭代器应该适用于在一个循环中循环整个向量,不知道它在两个循环中有多大的意义。


I am creating a Matrix<T> class. While implementing iterators for it I stumbled upon a design conundrum.

Internally, the matrix holds the data in a std::vector<T> (row-major).
One way of iterating through the matrix is by double iterators (nested) (specified by the row_double template parameter):

for (auto it_i = mat.Begin<row_double>(); it_i < mat.End<row_double>(); ++it_i) {
  for (auto it_j = it_i->Begin(); it_j < it_i->End(); ++it_j) {
    cout << *it_j << " ";
  }
  cout << endl;    
}

The first iterator Matrix<T>::Iterator<row_double>:

  • iterates through the rows of the matrix
  • has a RowProxy member
  • Dereferencing it returns a RowProxy.

RowProxy returns std::vector<T>::iterator iterators via methods like Begin() and End().

My idea is for the RowProxy to know the beginning of the line and the size of the line (number of matrix columns).

The problem is how RowProxy holds the beginning of the line reference:

  • My first approach was to make the beginning of the line a std::vector<T>::iterator.
    The problem is that in Visual Studio the iterator is aware of the vector and there are debug checks for iterator arithmetics. It throws an error when constructing the ReverseEnd iterator (for the line before the first line): the beginning of the line is num_columns before the vector start. please note that this has nothing to do with dereferencing (whitch is UB). I can't create the iterator..

  • My second approach was to make the beginning of the line a raw pointer T *
    The problem here is that LineProxy needs to return std::vector<T>::iterator (via it's own Begin etc.) and I cannot (don't know how to) construct a std::vector<T>::iterator from a T * in a standard way. (Didn't find any reference specific to std::vector<T>::iterator, just iterator concepts. In visual Studio there seems to be a constructor (T *, std::vector<T> *), in gcc a (T *), neither one works in the other compiler).

The solution that I see now is to make my own iterator identical with std::vector<T>::iterator but who isn't bound to any vector and can be constructed from T * and make RowProxy return that. But this really seems like reinventing the wheel.

Since this is part of a library (and the code resides in headers), compiler options are out of the question (including macros that control compiler options because they modify the whole behaviour of the program that includes the header, not just the behaviour of the library code). Also the solution must be conforming to the standard. The language is C++11.

解决方案

The simplest way to do this as stated above is to use Eigen, it is really a very nice package. The next simplest thing to do would be to store size information in your class then you have a very nice way of getting a specific element out of your matrix. Just write an (i,j) operator that returns vector[i + j*rowlength]. Iterators should work well for looping over the whole vector in one loop, not sure how much sense it makes to loop over in two.

这篇关于为Matrix类设计迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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