今回は除算以外の算術二項演算子と論理演算子を実装してみる。
// 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+()を定義するよくある実装を使った。
次回はいよいよ、余因子行列と行列式を定義してみたい。