Reputation: 137
I am writing custom class Matrix using two-dimensional std::vector. So the problem is that I need to overload ++ operation for iterators so that I can run through the entire matrix at a time.
template <typename T>
class Matrix {
private:
std::vector<std::vector<T>> arr;
public:
Matrix(const std::vector<std::vector<T>>& tmp) {
arr = tmp;
}
std::pair<size_t, size_t> size() const {
std::pair<size_t, size_t> tmp;
if (arr.empty()) {
tmp.first = 0;
tmp.second = 0;
} else {
tmp.first = arr.size();
tmp.second = arr[0].size();
}
return tmp;
}
T operator () (size_t i, size_t j) const {
return arr[i][j];
}
Matrix& transpose() {
std::vector<std::vector<T>> tmp(size().second, std::vector<T>(size().first));
for (size_t i = 0; i < size().first; ++i) {
for (size_t j = 0; j < size().second; ++j) {
tmp[j][i] = arr[i][j];
}
}
*this = Matrix(tmp);
return *this;
}
Matrix transposed() const {
std::vector<std::vector<T>> tmp(size().second, std::vector<T>(size().first));
for (size_t i = 0; i < size().first; ++i) {
for (size_t j = 0; j < size().second; ++j) {
tmp[j][i] = arr[i][j];
}
}
return Matrix(tmp);
}
typename std::vector<T>::iterator begin() {
return arr[0].begin();
}
typename std::vector<T>::iterator end() {
return arr[size().first-1].end();
}
};
For example, with the matrix mat = {{1,2},{3,4}}, this should work:
vector<vector<int>> arr = {{1,2},{3,4}};
Matrix mar(arr);
auto it = mat.begin();
while (it != mat.end()) {
cout << *it << " ";
}
and the output should be:
1 2 3 4
Can you please help me how to overload operator++()
, begin()
and end()
for std::vector
iterators?
Upvotes: 2
Views: 534
Reputation: 137
So the decision using one-dimension(doesn't sound right) vector works. Thx everyone!
#include <iostream>
#include <utility>
#include <vector>
template <typename T>
class Matrix {
private:
std::vector<T> arr;
size_t m = 0;
size_t n = 0;
public:
Matrix(const std::vector<std::vector<T>>& tmp) {
for (const auto& row : tmp) {
for (const auto& x : row) {
arr.push_back(x);
}
}
if (!tmp.empty()) {
m = tmp.size();
n = tmp[0].size();
}
}
std::pair<size_t, size_t> size() const {
std::pair<size_t, size_t> tmp;
tmp.first = m;
tmp.second = n;
return tmp;
}
T operator () (size_t i, size_t j) const {
return arr[i * m + j];
}
Matrix transposed() const {
std::vector<std::vector<T>> tmp(size().second, std::vector<T>(size().first));
for (size_t i = 0; i < size().first; ++i) {
for (size_t j = 0; j < size().second; ++j) {
tmp[j][i] = arr[i * m + j];
}
}
return Matrix(tmp);
}
Matrix& transpose() {
*this = transposed();
return *this;
}
auto begin() {
return arr.begin();
}
auto end() {
return arr.end();
}
auto begin() const {
return arr.begin();
}
auto end() const {
return arr.end();
}
};
template <typename T>
std::ostream& operator<<(std::ostream& out, const Matrix<T>& m) {
for (size_t i = 0; i < m.size().first; ++i) {
for (size_t j = 0; j < m.size().second; ++j) {
if (j == 0)
out << m(i, j);
else
out << "\t" << m(i, j);
}
if (i != m.size().first - 1)
out << "\n";
}
return out;
}
template <typename T>
Matrix<T> operator + (const Matrix<T>& m1, const Matrix<T>& m2) {
std::vector<std::vector<T>> tmp(m1.size().first, std::vector<T>(m1.size().second));
for (size_t i = 0; i < m1.size().first; ++i) {
for (size_t j = 0; j < m1.size().second; ++j) {
tmp[i][j] = m1(i, j) + m2(i, j);
}
}
return Matrix(tmp);
}
template <typename T>
Matrix<T>& operator += (Matrix<T>& m1, const Matrix<T>& m2) {
m1 = m1 + m2;
return m1;
}
template <typename T1, typename T2>
Matrix<T1> operator * (const Matrix<T1>& m, const T2& x) {
std::vector<std::vector<T1>> tmp(m.size().first, std::vector<T1>(m.size().second));
for (size_t i = 0; i < m.size().first; ++i) {
for (size_t j = 0; j < m.size().second; ++j) {
tmp[i][j] = m(i, j) * x;
}
}
return Matrix(tmp);
}
template <typename T1, typename T2>
Matrix<T1> operator * (const T2& x, const Matrix<T1>& m) {
return m * x;
}
template <typename T1, typename T2>
Matrix<T1>& operator *= (Matrix<T1>& m, const T2& x) {
m = m * x;
return m;
}
template <typename T>
Matrix<T> operator * (const Matrix<T>& first, const Matrix<T>& second) {
std::vector<std::vector<T>> tmp(first.size().first, std::vector<T>(second.size().second));
T x = 0;
for (size_t i = 0; i < first.size().first; ++i) {
for (size_t j = 0; j < second.size().second; ++j) {
for (size_t k = 0; k < first.size().second; ++k) {
x += first(i, k) * second(k, j);
}
tmp[i][j] = x;
x = 0;
}
}
return Matrix(tmp);
}
template <typename T>
Matrix<T>& operator *= (Matrix<T>& first, const Matrix<T>& second) {
first = first * second;
return first;
}
Upvotes: 1
Reputation: 132056
I am writing custom class Matrix using two-dimensional std::vector.
Don't do that. Why?
std::vector
s; you mean, a vector-of-vectors (which is what your example has). This will usually be somewhat slow, and besides - its semantics is probably not what you want (e.g. ability to resize individual rows, row storage scattered all over the heap etc.)You might want to consider, for an example off the top of my head, the Eigen library's matrix class.
Upvotes: 2
Reputation: 1498
You will not be able to just take an iterator returned by std::vector and change any of its methods. If you want to, create your own iterator class (one that, for example, cointains two iterators into your internal vectors), that your matrix class will return, and implement the relevant methods for them.
Upvotes: 2