#include <iostream>
#include <vector>
#include <initializer_list>
#include <utility>
namespace stdx {
template <typename T, typename Allocator>
class matrix;
template<typename T, typename Allocator = std::allocator<T>>
class matrix_helper {
public:
friend class matrix<T, Allocator>;
using o_matrix = matrix<T, Allocator>;
using p_vector = std::vector<T, Allocator>;
using v_size_t = typename p_vector::size_type;
typename p_vector::reference operator [] (v_size_t colindex) {
return static_cast<p_vector &>(matrix_)[rowindex_ * matrix_.rowsize() + colindex];
}
operator typename p_vector::reference () {
return static_cast<p_vector &>(matrix_)[rowindex_];
}
typename p_vector::reference operator = (T &&value) {
return (typename p_vector::reference)(*this) = std::forward<T>(value);
}
protected:
matrix_helper(o_matrix &matrix, v_size_t rowindex) :
matrix_(matrix),
rowindex_(rowindex)
{}
protected:
o_matrix &matrix_;
v_size_t rowindex_;
};
template<typename T, typename Allocator = std::allocator<T>>
class const_matrix_helper : public matrix_helper<T, Allocator> {
public:
friend class matrix<T, Allocator>;
using o_matrix = matrix<T, Allocator>;
using p_vector = std::vector<T, Allocator>;
using v_size_t = typename p_vector::size_type;
typename p_vector::const_reference operator [] (v_size_t colindex) const {
return const_cast<matrix_helper<T, Allocator> *>(this)->operator [](colindex);
}
operator typename p_vector::const_reference () const {
return (typename p_vector::reference) const_cast<matrix_helper<T, Allocator> *>(this);
}
protected:
const_matrix_helper(const o_matrix &matrix, v_size_t rowindex) :
matrix_helper<T, Allocator>(const_cast<o_matrix &>(matrix), rowindex)
{}
};
template <typename T, typename Allocator = std::allocator<T>>
class matrix : public std::vector<T, Allocator> {
public:
using p_vector = std::vector<T, Allocator>;
using v_size_t = typename p_vector::size_type;
matrix(std::initializer_list<std::initializer_list<T>> contents)
{
for (auto &row : contents) {
rowsize_ = row.size();
p_vector::insert(p_vector::end(), row);
}
}
matrix(typename p_vector::size_type rowsize, std::initializer_list<T> contents) :
p_vector(contents),
rowsize_(rowsize)
{}
v_size_t rowsize() const {
return rowsize_;
}
v_size_t colsize() const {
return p_vector::size() / rowsize_;
}
const const_matrix_helper<T, Allocator> operator [] (v_size_t rowindex) const {
return const_matrix_helper<T, Allocator>(*this, rowindex);
}
matrix_helper<T, Allocator> operator [] (v_size_t rowindex) {
return matrix_helper<T, Allocator>(*this, rowindex);
}
private:
static constexpr v_size_t invalid_size = -1;
v_size_t rowsize_ = invalid_size;
};
}
using std::cout;
using std::endl;
int main(int argc, char *argv[])
{
(void) argc;
(void) argv;
stdx::matrix<int> m0 = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
cout << "m0[1, 2] = " << m0[1][2] << endl;
cout << "m0[1] = " << (int) m0[1] << endl;
m0[1][2] = 42;
m0[1] = 3;
cout << "After change:\n" << endl;
cout << "m0[1, 2] = " << m0[1][2] << endl;
cout << "m0[1] = " << (int) m0[1] << endl;
stdx::matrix<int> m1(2, { 1, 2, 3, 4 });
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8aW5pdGlhbGl6ZXJfbGlzdD4KI2luY2x1ZGUgPHV0aWxpdHk+CgpuYW1lc3BhY2Ugc3RkeCB7Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgQWxsb2NhdG9yPgpjbGFzcyBtYXRyaXg7Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSBBbGxvY2F0b3IgPSBzdGQ6OmFsbG9jYXRvcjxUPj4KY2xhc3MgbWF0cml4X2hlbHBlciB7CnB1YmxpYzoKICAgIGZyaWVuZCBjbGFzcyBtYXRyaXg8VCwgQWxsb2NhdG9yPjsKCiAgICB1c2luZyBvX21hdHJpeCA9IG1hdHJpeDxULCBBbGxvY2F0b3I+OwogICAgdXNpbmcgcF92ZWN0b3IgPSBzdGQ6OnZlY3RvcjxULCBBbGxvY2F0b3I+OwogICAgdXNpbmcgdl9zaXplX3QgPSB0eXBlbmFtZSBwX3ZlY3Rvcjo6c2l6ZV90eXBlOwoKICAgIHR5cGVuYW1lIHBfdmVjdG9yOjpyZWZlcmVuY2Ugb3BlcmF0b3IgW10gKHZfc2l6ZV90IGNvbGluZGV4KSB7CiAgICAgICAgcmV0dXJuIHN0YXRpY19jYXN0PHBfdmVjdG9yICY+KG1hdHJpeF8pW3Jvd2luZGV4XyAqIG1hdHJpeF8ucm93c2l6ZSgpICsgY29saW5kZXhdOwogICAgfQoKICAgIG9wZXJhdG9yIHR5cGVuYW1lIHBfdmVjdG9yOjpyZWZlcmVuY2UgKCkgewogICAgICAgIHJldHVybiBzdGF0aWNfY2FzdDxwX3ZlY3RvciAmPihtYXRyaXhfKVtyb3dpbmRleF9dOwogICAgfQoKICAgIHR5cGVuYW1lIHBfdmVjdG9yOjpyZWZlcmVuY2Ugb3BlcmF0b3IgPSAoVCAmJnZhbHVlKSB7CiAgICAgICAgcmV0dXJuICh0eXBlbmFtZSBwX3ZlY3Rvcjo6cmVmZXJlbmNlKSgqdGhpcykgPSBzdGQ6OmZvcndhcmQ8VD4odmFsdWUpOwogICAgfQoKcHJvdGVjdGVkOgogICAgbWF0cml4X2hlbHBlcihvX21hdHJpeCAmbWF0cml4LCB2X3NpemVfdCByb3dpbmRleCkgOgogICAgICAgIG1hdHJpeF8obWF0cml4KSwKICAgICAgICByb3dpbmRleF8ocm93aW5kZXgpCiAgICB7fQoKcHJvdGVjdGVkOgogICAgb19tYXRyaXggJm1hdHJpeF87CiAgICB2X3NpemVfdCByb3dpbmRleF87Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSBBbGxvY2F0b3IgPSBzdGQ6OmFsbG9jYXRvcjxUPj4KY2xhc3MgY29uc3RfbWF0cml4X2hlbHBlciA6IHB1YmxpYyBtYXRyaXhfaGVscGVyPFQsIEFsbG9jYXRvcj4gewpwdWJsaWM6CiAgICBmcmllbmQgY2xhc3MgbWF0cml4PFQsIEFsbG9jYXRvcj47CgogICAgdXNpbmcgb19tYXRyaXggPSBtYXRyaXg8VCwgQWxsb2NhdG9yPjsKICAgIHVzaW5nIHBfdmVjdG9yID0gc3RkOjp2ZWN0b3I8VCwgQWxsb2NhdG9yPjsKICAgIHVzaW5nIHZfc2l6ZV90ID0gdHlwZW5hbWUgcF92ZWN0b3I6OnNpemVfdHlwZTsKCiAgICB0eXBlbmFtZSBwX3ZlY3Rvcjo6Y29uc3RfcmVmZXJlbmNlIG9wZXJhdG9yIFtdICh2X3NpemVfdCBjb2xpbmRleCkgY29uc3QgewogICAgICAgIHJldHVybiBjb25zdF9jYXN0PG1hdHJpeF9oZWxwZXI8VCwgQWxsb2NhdG9yPiAqPih0aGlzKS0+b3BlcmF0b3IgW10oY29saW5kZXgpOwogICAgfQoKICAgIG9wZXJhdG9yIHR5cGVuYW1lIHBfdmVjdG9yOjpjb25zdF9yZWZlcmVuY2UgKCkgY29uc3QgewogICAgICAgIHJldHVybiAodHlwZW5hbWUgcF92ZWN0b3I6OnJlZmVyZW5jZSkgY29uc3RfY2FzdDxtYXRyaXhfaGVscGVyPFQsIEFsbG9jYXRvcj4gKj4odGhpcyk7CiAgICB9Cgpwcm90ZWN0ZWQ6CiAgICBjb25zdF9tYXRyaXhfaGVscGVyKGNvbnN0IG9fbWF0cml4ICZtYXRyaXgsIHZfc2l6ZV90IHJvd2luZGV4KSA6CiAgICAgICAgbWF0cml4X2hlbHBlcjxULCBBbGxvY2F0b3I+KGNvbnN0X2Nhc3Q8b19tYXRyaXggJj4obWF0cml4KSwgcm93aW5kZXgpCiAgICB7fQp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIEFsbG9jYXRvciA9IHN0ZDo6YWxsb2NhdG9yPFQ+PgpjbGFzcyBtYXRyaXggOiBwdWJsaWMgc3RkOjp2ZWN0b3I8VCwgQWxsb2NhdG9yPiB7CnB1YmxpYzoKICAgIHVzaW5nIHBfdmVjdG9yID0gc3RkOjp2ZWN0b3I8VCwgQWxsb2NhdG9yPjsKICAgIHVzaW5nIHZfc2l6ZV90ID0gdHlwZW5hbWUgcF92ZWN0b3I6OnNpemVfdHlwZTsKCiAgICBtYXRyaXgoc3RkOjppbml0aWFsaXplcl9saXN0PHN0ZDo6aW5pdGlhbGl6ZXJfbGlzdDxUPj4gY29udGVudHMpCiAgICB7CiAgICAgICAgZm9yIChhdXRvICZyb3cgOiBjb250ZW50cykgewogICAgICAgICAgICByb3dzaXplXyA9IHJvdy5zaXplKCk7CiAgICAgICAgICAgIHBfdmVjdG9yOjppbnNlcnQocF92ZWN0b3I6OmVuZCgpLCByb3cpOwogICAgICAgIH0KICAgIH0KCiAgICBtYXRyaXgodHlwZW5hbWUgcF92ZWN0b3I6OnNpemVfdHlwZSByb3dzaXplLCBzdGQ6OmluaXRpYWxpemVyX2xpc3Q8VD4gY29udGVudHMpIDoKICAgICAgICBwX3ZlY3Rvcihjb250ZW50cyksCiAgICAgICAgcm93c2l6ZV8ocm93c2l6ZSkKICAgIHt9CgogICAgdl9zaXplX3Qgcm93c2l6ZSgpIGNvbnN0IHsKICAgICAgICByZXR1cm4gcm93c2l6ZV87CiAgICB9CgogICAgdl9zaXplX3QgY29sc2l6ZSgpIGNvbnN0IHsKICAgICAgICByZXR1cm4gcF92ZWN0b3I6OnNpemUoKSAvIHJvd3NpemVfOwogICAgfQoKICAgIGNvbnN0IGNvbnN0X21hdHJpeF9oZWxwZXI8VCwgQWxsb2NhdG9yPiBvcGVyYXRvciBbXSAodl9zaXplX3Qgcm93aW5kZXgpIGNvbnN0IHsKICAgICAgICByZXR1cm4gY29uc3RfbWF0cml4X2hlbHBlcjxULCBBbGxvY2F0b3I+KCp0aGlzLCByb3dpbmRleCk7CiAgICB9CgogICAgbWF0cml4X2hlbHBlcjxULCBBbGxvY2F0b3I+IG9wZXJhdG9yIFtdICh2X3NpemVfdCByb3dpbmRleCkgewogICAgICAgIHJldHVybiBtYXRyaXhfaGVscGVyPFQsIEFsbG9jYXRvcj4oKnRoaXMsIHJvd2luZGV4KTsKICAgIH0KCnByaXZhdGU6CiAgICBzdGF0aWMgY29uc3RleHByIHZfc2l6ZV90IGludmFsaWRfc2l6ZSA9IC0xOwogICAgdl9zaXplX3Qgcm93c2l6ZV8gPSBpbnZhbGlkX3NpemU7Cn07Cgp9Cgp1c2luZyBzdGQ6OmNvdXQ7CnVzaW5nIHN0ZDo6ZW5kbDsKCmludCBtYWluKGludCBhcmdjLCBjaGFyICphcmd2W10pCnsKICAgICh2b2lkKSBhcmdjOwogICAgKHZvaWQpIGFyZ3Y7CgogICAgc3RkeDo6bWF0cml4PGludD4gbTAgPSB7CiAgICAgICAgeyAxLCAyLCAzIH0sCiAgICAgICAgeyA0LCA1LCA2IH0sCiAgICAgICAgeyA3LCA4LCA5IH0KICAgIH07CgogICAgY291dCA8PCAibTBbMSwgMl0gPSAiIDw8IG0wWzFdWzJdIDw8IGVuZGw7CiAgICBjb3V0IDw8ICJtMFsxXSA9ICIgPDwgKGludCkgbTBbMV0gPDwgZW5kbDsKCiAgICBtMFsxXVsyXSA9IDQyOwogICAgbTBbMV0gPSAzOwoKICAgIGNvdXQgPDwgIkFmdGVyIGNoYW5nZTpcbiIgPDwgZW5kbDsKICAgIGNvdXQgPDwgIm0wWzEsIDJdID0gIiA8PCBtMFsxXVsyXSA8PCBlbmRsOwogICAgY291dCA8PCAibTBbMV0gPSAiIDw8IChpbnQpIG0wWzFdIDw8IGVuZGw7CgogICAgc3RkeDo6bWF0cml4PGludD4gbTEoMiwgeyAxLCAyLCAzLCA0IH0pOwoKICAgIHJldHVybiAwOwp9Cg==