我正在创建一个Matrix<T>
课程。在为它实现迭代器时,我偶然发现了一个设计难题。
在内部,矩阵将数据保存在std::vector<T>
(行主要)中
迭代矩阵的一种方法是使用双迭代器(嵌套)(由row_double
模板参数指定):
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
。 RowProxy
通过std::vector<T>::iterator
和Begin()
等方法返回End()
个迭代器。
我的想法是让RowProxy
知道行的开头和行的大小(矩阵列的数量)。
问题是RowProxy
保存行引用开头的方式:
我的第一个方法是将行的开头设为std::vector<T>::iterator
问题是在Visual Studio中,迭代器知道向量,并且对迭代器算术进行了调试检查。在构造ReverseEnd
迭代器(对于第一行之前的行)时抛出错误:在num_columns
开始之前,行的开头是vector
。 请注意,这与解除引用无关(whitch是UB)。我无法创建迭代器。 。
我的第二种方法是使行的开头成为原始指针T *
这里的问题是LineProxy
需要返回std::vector<T>::iterator
(通过它自己的Begin
等)而我不能(不知道如何)构建{来自std::vector<T>::iterator
的{1}}标准方式。 (没有找到任何特定于T *
的引用,只是迭代器概念。在Visual Studio中似乎有一个构造函数std::vector<T>::iterator
,在gcc a (T *, std::vector<T> *)
中,两个都没有在其他编译器。)
我现在看到的解决方案是让我自己的迭代器与(T *)
相同,但是谁不与任何std::vector<T>::iterator
绑定,并且可以从vector
构建并生成{ {1}}返回。但这真的好像重新发明轮子。
由于这是库的一部分(并且代码驻留在头文件中),编译器选项是不可能的(包括控制编译器选项的宏,因为它们会修改包含头的程序的整个行为,而不仅仅是库代码的行为)。解决方案也必须符合标准。语言为T *
。
答案 0 :(得分:-3)
如上所述,最简单的方法是使用Eigen,它实际上是一个非常好的包。接下来最简单的事情就是在您的类中存储大小信息,然后您可以通过非常好的方式从矩阵中获取特定元素。只需编写一个返回vector [i + j * rowlength]的(i,j)运算符。迭代器应该可以很好地在一个循环中循环遍历整个向量,不确定它在两个循环中有多大意义。