[英]c++ implementing iterators for custom matrix class
我目前正在研究用於教育目的和個人用途的線性代數庫(自定義矢量和矩陣以及一些算法)。 我試圖實現一個列迭代器,該遍歷器遍歷Matrix的指定列。
這是向量類的代碼示例(基於該類的矩陣類):
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
};
矩陣類基於此向量(或與此有關的std :: vector),看起來像:
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
};
因此,迭代行工作正常,我要做的就是:
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類文章的Designing迭代器聽起來與我的問題和情況非常相似,但是我無法得出該問題的解決方案。
其他建議指出了Boost庫的迭代器:特別是:
boost::adaptors::stride(rng, n)
boost::adaptors::slice(rng, n, m)
確實提供了非常相似的所需結果。 但是我的get_column函數也是如此。 但是,我不想創建一個新對象。 提升功能是做什么的。 來自文檔“返回:基於rng的新范圍,其中以n為步長執行遍歷”。
因此,似乎迭代器不知道何時停止。
因此,我回到了第一個平方:如何返回迭代通過存儲為向量的Matrix的列的迭代器?
我找到了解決問題的辦法。 它是以下各項的組合:
this: 獲取迭代器范圍的每個第n個元素,以及this: http : //www.codeproject.com/Questions/331444/How-to-use-boost-filter-iterator-as-a-class-member
最后,沒有辦法解決問題。 該解決方案非常簡單,看起來像:
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)而不是兩個:
bash-3.2$ ./main
1 4 7
這正是預期的結果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.