#include <vector>
#include <utility>
#include <iostream>

template <typename T>
class Matrix
{
private:
    class Row
    {
    friend class Matrix;

    public:
        T& operator[] (int j) &&
        {
            return matrix->mappedVector[i * matrix->n + j];
        }
        const T& operator[] (int j) const &&
        {
            return matrix->mappedVector[i * matrix->n + j];
        }
    private:
        int i;
        Matrix* matrix;

        Row(int i, const Matrix* matrix):
            i(i),
            matrix(const_cast<Matrix*>(matrix))
        {
        	std::cout << "int ctor" << std::endl;
        }
        Row(int i, Matrix* matrix):
            i(i),
            matrix(matrix)
        {
        	std::cout << "int ctor" << std::endl;
        }
        Row()
        {
            std::cout << "ctor" << std::endl;
        }
        Row(const Row&)
        {
            std::cout << "copy ctor" << std::endl;
        }
        Row& operator=(const Row&)
        {
            std::cout << "assign lvalue" << std::endl;
        }
        Row(Row&&)
        {
            std::cout << "move ctor" << std::endl;
        }
        Row& operator=(Row&&)
        {
            std::cout << "assign rvalue" << std::endl;
        }
    };
public:
    Matrix():
        m(0),
        n(0)
    {}
    explicit Matrix(size_t m, size_t n):
        m(m),
        n(n),
        mappedVector(m*n)
    {}
    Matrix(const Matrix& rhs):
        m(rhs.m),
        n(rhs.n),
        mappedVector(rhs.mappedVector)
    {}
    Matrix& operator=(const Matrix& rhs)
    {
        if(&rhs != this)
        {
            m = rhs.m;
            n = rhs.m;
            mappedVector.resize(rhs.mappedVector.size);
            mappedVector = rhs.mappedVector;
        }
    }
    Matrix(Matrix&& rhs):
        m(std::exchange(rhs.m, 0)),
        n(std::exchange(rhs.n, 0)),
        mappedVector(std::exchange(rhs.mappedVector, {}))
    {}
    Matrix& operator=(Matrix&& rhs)
    {
        if(&rhs != this)
        {
            m = std::exchange(rhs.m, 0);
            n = std::exchange(rhs.n, 0);
            mappedVector = std::exchange(rhs.mappedVector, {});
        }
    }
    Row operator[] (int i)
    {
        return Row(i, this);
    }
    const Row operator[] (int i) const
    {
        return Row(i, this);
    }
private:
    size_t m;
    size_t n;
    std::vector<T> mappedVector;
};

int main()
{
	Matrix<int> matrix(2, 5);
    matrix[1][0] = 1;
    
    auto autoRowProxy = matrix[1];
    
	return 0;
}