Goal:
- Wrap a vector. The wrapper can create view on part of the vector.
- Support const_view and view.
- view allows modification of elements while const_view does not.
- The views are ranges (has begin() and end() methods).
Problem:
- Code duplication between the const_view and view.
The actual code implements a 2D sparse array that saves more memory than usual. So I want to learn how to solve this problem.
Simplified Code (implements a dense 2D array)
#include <vector>
class A_csub;
class A_sub;
typedef std::vector<int> V;
typedef typename V::iterator It;
typedef typename V::const_iterator Cit;
class A {
// 2D dense array with _r rows and _c columns.
public:
A(const int r, const int c);
A_csub cview(const int n) const;
A_sub view(const int n); // view nth row
It sub_begin(const int n); // iterator at begin of nth row
Cit sub_cbegin(const int n) const;
int _r;
int _c;
private:
V _v;
};
class A_csub {
public:
A_csub(const A& a, const int n);
Cit begin() const;
Cit end() const;
const int size() const;
private:
const A& _a;
const int _n;
};
class A_sub {
public:
A_sub(A& a, const int n);
It begin();
It end();
const int size() const;
private:
A& _a;
const int _n;
};
// -- A -- //
A::A(const int r, const int c) : _r(c), _c(c), _v(r*c) {}
A_csub A::cview(const int n) const { return A_csub(*this, n); }
A_sub A::view(const int n) { return A_sub(*this, n); }
It A::sub_begin(const int n) { return _v.begin() + n*_r; }
Cit A::sub_cbegin(const int n) const { return _v.cbegin() + n*_r; }
// -- A_csub -- //
A_csub::A_csub(const A& a, const int n) : _a(a), _n(n) {}
Cit A_csub::begin() const { return _a.sub_cbegin(_n); }
Cit A_csub::end() const { return begin() + _a._r; }
const int A_csub::size() const { return _a._r; }
// -- A_sub -- //
A_sub::A_sub(A& a, const int n) : _a(a), _n(n) {}
It A_sub::begin() { return _a.sub_begin(_n); }
It A_sub::end() { return begin() + _a._r; }
const int A_sub::size() const { return _a._r; }
int main() {
A a(10,5);
a.cview(4);
A_sub b = a.view(4);
for (auto && e:b) {e=1;}
}