0

I have a Matrix class

template <typename T>
class Matrix
{
public:
  const size_t rows;
  const size_t cols;
  const std::map<std::array<int, 2>, T> data;

  Matrix(int a, int b) : rows(a), cols(b)
  {
  }
};

which is initialized like this:

Matrix<double> M(5,5);

creating a 5x5 matrix.

I want to assign values to the map like so:

M[{1,2}] = 1;

How would I go about doing that in the most readable way? I'm not sure how to get the subscript and assignment operator working together.

Nick
  • 2,862
  • 5
  • 34
  • 68
  • 3
    "How would I go about doing that in the most readable way?" first of all by making data non const. – Slava Jan 25 '18 at 15:50
  • [Read this](https://stackoverflow.com/questions/6969881/operator-overload) or [this](https://stackoverflow.com/q/27221482/5267751). – user202729 Jan 25 '18 at 15:50
  • 5
    A std::map as matrix is a bad implementation. –  Jan 25 '18 at 15:50
  • 2
    @manni66 not according to my literature when dealing with sparse matrices – Nick Jan 25 '18 at 15:56
  • @Ortix92 I would be interested in seeing that literature. – François Andrieux Jan 25 '18 at 15:57
  • 2
    @FrançoisAndrieux it's on my scientific computing class' slides and in the reader, so I'll stick with that for now. I know there are far superior methods and I don't like reinventing the wheel either, but it's what I have to deal with now. – Nick Jan 25 '18 at 16:00
  • 3
    @FrançoisAndrieux it's overkill for `M(5,5)`, but is more obviously useful for `M(500000,500000)` – Caleth Jan 25 '18 at 16:05
  • @Caleth I don't see how. Calculating an index in a flat vector and accessing the element is constant time. Accessing an element in a `std::map` has logarithmic time complexity. Meaning that `std::vector` becomes a more attractive solution as the size of the matrix grows. – François Andrieux Jan 25 '18 at 16:09
  • 3
    @FrançoisAndrieux not for **sparse** matrices – bolov Jan 25 '18 at 16:10
  • @bolov Thanks, I missed that part of the context. – François Andrieux Jan 25 '18 at 16:11
  • 1
    I would recommend replacing `std::array` with `std::pair` – bolov Jan 25 '18 at 16:12
  • 2
    @bolov I would recommend making a separate class for this – Sopel Jan 25 '18 at 16:14
  • 2
    I actually think OP is fine with `std::array` here, all they need is something that can be list initialized with 2 indexes – Caleth Jan 25 '18 at 16:56

2 Answers2

6

Let's add some helper aliases to Matrix while we are at it

template <typename T>
class Matrix
{   
    // rather than stoping people changing the members via const
    // make them private
    size_t rows;
    size_t cols;
    map_type data;
public:
    using key_type = std::array<size_t, 2>;
    using mapped_type = T;
    using map_type = std::map<key_type, mapped_type>;

    Matrix(size_t r, size_t c) : rows(r), cols(c) { }

    const T& operator [](key_type key) const { return data[key]; }
          T& operator [](key_type key)       { return data[key]; }

    // other operations as appropriate
};
Caleth
  • 52,200
  • 2
  • 44
  • 75
3

You have to provide members:

const T& operator [](std::pair<std::size_t, std::size_t>) const;
      T& operator [](std::pair<std::size_t, std::size_t>);
bolov
  • 72,283
  • 15
  • 145
  • 224
Jarod42
  • 203,559
  • 14
  • 181
  • 302