今回は除算以外の算術二項演算子と論理演算子を実装してみる。
// matrix.cpp #include <iostream> #include <initializer_list> template <typename T, int N> class Matrix { static_assert(N > 0, ""); public: //------------------------------------------ // // 挿入演算子 // //------------------------------------------ friend std::ostream& operator <<(std::ostream& os, const Matrix& x) { os << "["; for (int iRow = 0; iRow < N; iRow++) { os << "["; for (int iColumn = 0; iColumn < N; iColumn++) { os << x.elements_[iRow][iColumn]; if (iColumn != N - 1) os << ","; } os << "]"; if (iRow != N - 1) os << ","; } os << "]"; return os; } public: //------------------------------------------ // // コンストラクタ、デストラクタ、コピー、ムーブ // //------------------------------------------ Matrix() noexcept(noexcept(T())) {} Matrix(const T& a) { for (int i = 0; i < N; i++) elements_[i][i] = a; } Matrix(std::initializer_list<std::initializer_list<T>> ll) { auto itRow = ll.begin(); for (int iRow = 0; iRow < N && itRow != ll.end(); iRow++, ++itRow) { auto l = *itRow; auto itColumn = l.begin(); for (int iColumn = 0; iColumn < N && itColumn != l.end(); iColumn++, ++itColumn) { elements_[iRow][iColumn] = *itColumn; } } } Matrix(const Matrix&) noexcept = default; Matrix(Matrix&&) noexcept = default; ~Matrix() = default; Matrix& operator =(const Matrix&) & noexcept = default; Matrix& operator =(Matrix&&) & noexcept = default; Matrix&& operator =(const Matrix&) && noexcept = delete; Matrix&& operator =(Matrix&&) && noexcept = delete; public: //------------------------------------------ // // 要素の参照 // //------------------------------------------ T& operator ()(int row, int column) { return elements_[row][column]; } const T& operator ()(int row, int column) const { return elements_[row][column]; } public: //------------------------------------------ // // 算術単項演算子 // //------------------------------------------ Matrix operator +() const { return Matrix(*this); } Matrix operator -() const { Matrix ret; for (int iRow = 0; iRow < N; iRow++) { for (int iColumn = 0; iColumn < N; iColumn++) { ret.elements_[iRow][iColumn] = -elements_[iRow][iColumn]; } } return ret; } public: //------------------------------------------ // // 算術代入演算子 // //------------------------------------------ Matrix& operator +=(const Matrix& other) & { for (int iRow = 0; iRow < N; iRow++) { for (int iColumn = 0; iColumn < N; iColumn++) { elements_[iRow][iColumn] += other.elements_[iRow][iColumn]; } } return *this; } Matrix& operator -=(const Matrix& other) & { for (int iRow = 0; iRow < N; iRow++) { for (int iColumn = 0; iColumn < N; iColumn++) { elements_[iRow][iColumn] -= other.elements_[iRow][iColumn]; } } return *this; } Matrix& operator *=(const T& a) & { for (int iRow = 0; iRow < N; iRow++) { for (int iColumn = 0; iColumn < N; iColumn++) { elements_[iRow][iColumn] *= a; } } return *this; } Matrix& operator *=(const Matrix& other) & { Matrix tmp = *this * other; using std::swap; swap(*this, tmp); return *this; } Matrix&& operator +=(const Matrix& other) && = delete; Matrix&& operator -=(const Matrix& other) && = delete; Matrix&& operator *=(const T& a) && = delete; Matrix&& operator *=(const Matrix& other) && = delete; public: //------------------------------------------ // // 算術二項演算子 // //------------------------------------------ friend Matrix operator +(const Matrix& lhs, const Matrix& rhs) { Matrix ret(lhs); return ret += rhs; } friend Matrix operator -(const Matrix& lhs, const Matrix& rhs) { Matrix ret(lhs); return ret -= rhs; } friend Matrix operator *(const Matrix& lhs, const T& rhs) { Matrix ret(lhs); return ret *= rhs; } friend Matrix operator *(const T& lhs, const Matrix& rhs) { return rhs *= lhs; } friend Matrix operator *(const Matrix& lhs, const Matrix& rhs) { Matrix ret; for (int iRow = 0; iRow < N; iRow++) { for (int iColumn = 0; iColumn < N; iColumn++) { for (int i = 0; i < N; i++) { ret.elements_[iRow][iColumn] += lhs.elements_[iRow][i] * rhs.elements_[i][iColumn]; } } } return ret; } public: //------------------------------------------ // // 論理演算子 // //------------------------------------------ friend bool operator ==(const Matrix& lhs, const Matrix& rhs) { for (int iRow = 0; iRow < N; iRow++) { for (int iColumn = 0; iColumn < N; iColumn++) { if (lhs.elements_[iRow][iColumn] != rhs.elements_[iRow][iColumn]) return false; } } return true; } friend bool operator !=(const Matrix& lhs, const Matrix& rhs) { return !(lhs == rhs); } private: T elements_[N][N] = {}; }; // class Matrix int main() { Matrix<int, 3> x{{1,2,3},{4,5,6},{7,8,9}}; Matrix<int, 3> y = x; y += x; std::cout << y << std::endl; std::cout << std::boolalpha << (x == (y - x)) << std::endl; return 0; }
実行結果は
[[2,4,6],[8,10,12],[14,16,18]]
true
のようになる。
operator+=()を使って、operator+()を定義するよくある実装を使った。
次回はいよいよ、余因子行列と行列式を定義してみたい。
0 件のコメント :
コメントを投稿