Итератор оператора ++, перегружающий C ++ - PullRequest
2 голосов
/ 02 марта 2020

Я пишу пользовательский класс Matrix с использованием двумерного std :: vector. Поэтому проблема заключается в том, что мне нужно перегрузить операцию ++ для итераторов, чтобы я мог проходить всю матрицу за раз.

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();
    }
};

Например, с матрицей mat = {{1,2} , {3,4}}, это должно работать:

vector<vector<int>> arr = {{1,2},{3,4}};
Matrix mar(arr);
auto it = mat.begin();
while (it != mat.end()) {
    cout << *it << " ";
}

и вывод должен быть:

1 2 3 4 

Можете ли вы помочь мне, как перегрузить operator++(), begin() и end() для std::vector итераторов?

Ответы [ 3 ]

2 голосов
/ 02 марта 2020

Я пишу пользовательский класс Matrix с использованием двумерного std :: vector.

Не делайте этого. Почему?

  1. Вы заново изобретаете колесо. Вряд ли ваш вариант использования настолько особенный, что ни одна из существующих библиотек матричной / линейной алгебры не соответствует вашим потребностям.
  2. Нет двухмерных std::vector s; Вы имеете в виду вектор векторов (который есть в вашем примере). Обычно это будет несколько медленным, и, кроме того, его семантика, вероятно, не та, которую вы хотите (например, возможность изменять размеры отдельных строк, хранение строк, разбросанных по всей куче и т. Д. c.)

Вы можете Я хочу рассмотреть, например, в верхней части моей головы, матричный класс Eigen библиотеки .

2 голосов
/ 02 марта 2020

Вы не сможете просто взять итератор, возвращаемый std :: vector, и изменить любой из его методов. Если вы хотите, создайте свой собственный класс итераторов (например, который содержит два итератора в ваших внутренних векторах), который будет возвращать ваш матричный класс, и реализуйте соответствующие методы для них.

1 голос
/ 03 марта 2020

Так что решение с использованием одномерного (не звучит правильно) вектора работает. Спасибо всем!

#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;
}

...