1

I'm building a Matrix class for all the operations such as addition, subtraction, multiplication, inverse etc. I have overloaded simple operators such as + - () *. But I'm trying to set a row and column value via ().

A sample would be like so

Matrix(1,1) = 10;

assuming that row 1, column 1 would be set to 10.

A sample of my addition overload is this

friend Matrix operator +(Matrix&, Matrix&);

How can I achieve this?

Thanks!

Austin Brunkhorst
  • 20,704
  • 6
  • 47
  • 61
  • 2
    A bit unrelated: your addition operator should be: `Matrix operator +(Matrix const&, Matrix const&);`. Otherwise, things like `x + y + z` just won't work. You can read more about this in the [operator overloading FAQ](http://stackoverflow.com/questions/4421706/operator-overloading). – R. Martinho Fernandes Mar 19 '12 at 22:53
  • @R.MartinhoFernandes can you elaborate the difference? – Austin Brunkhorst Mar 19 '12 at 22:54
  • 2
    Sure. `Matrix&` can only bind to lvalues (if you don't know what that is, let's say "named variables", which is not exactly correct, but it's close). `x + y + z` is the same as `operator+(operator+(x,y),z)`. The inner call returns a temporary object which is not an lvalue and thus cannot be passed to `Matrix&`. OTOH `Matrix const&` can bind to lvalues and to temporaries. – R. Martinho Fernandes Mar 19 '12 at 22:57
  • Why did you include the friend declaration of your addition operator? I don't see how it's relevant to your question. If any operator declaration is relevant, it would be for `operator()`. – Rob Kennedy Mar 19 '12 at 22:59
  • Here is my `()` operator: `double& operator ()(int, int);` – Austin Brunkhorst Mar 19 '12 at 23:03

3 Answers3

3

It's similar to what you've done already:

Value &operator()(int x, int y)
{
    return matrix[x][y]; // or whatever it's supposed to be
}

, where Value is your internal type.

However, I suggest instead using a setter function, since it is far less ambiguous. e.g.:

void set(int x, int y, Value v)
{
    matrix[x][y] = v;
}
jli
  • 6,523
  • 2
  • 29
  • 37
  • 1
    He's trying to set one of the values in the matrix, not perform an operation on two matrices. – Collin Mar 19 '12 at 22:52
  • I'm trying to **set** the value of the given matrix. As stated above, I already have this overload. I want something like `Matrix(row,column) = value;` – Austin Brunkhorst Mar 19 '12 at 22:53
  • @CollinHockey I edited it before you posted your comment, see updated. – jli Mar 19 '12 at 22:53
  • 1
    +1 This is quite correct. He says "It's similar to what you've done already", and that's confused you @CollinHockey, because his code is a bit different from, and not easy to infer from the code for `operator+`. @AustinBrunkhorst, the fact that the function returns a non-const `Value&` means that you can assign to the memory location pointed to by the reference. (Unfortunately, this means that you have to return a memory location that your user can just assign to, unlike in more modern scripting languages like Ruby that have `[]=` operators.) – Ken Bloom Mar 19 '12 at 22:57
  • @KenBloom, Actually, my original answer was wrong as I misinterpreted the question, but edited it about 3 or 4 seconds after posting :) – jli Mar 19 '12 at 22:58
  • What's ambiguous about `Matrix(row, col) = value;`? – Chris Lutz Mar 19 '12 at 22:59
  • @ChrisLutz I know it's being nitpicky, but if I was using a math library that used `operator()` as an accessor for an array type, it would be quite annoying. Why not `operator[]`? – jli Mar 19 '12 at 23:01
  • 1
    @jli: The grammar of the language demands that `operator[]` only take one single argument, so you just don't have that option. – Kerrek SB Mar 19 '12 at 23:04
  • @KerrekSB I was thinking `[][]` (where the first one returns a vector). – jli Mar 20 '12 at 00:02
  • 1
    @jli: That'd be non-trivial. You don't want to prescribe how the data is stored internally, and creating column and row views should probably be left to a separate, explicit interface. (Like `row(size_t)` and `col(size_t)`.) – Kerrek SB Mar 20 '12 at 00:04
  • @KerrekSB which is why I didn't initially suggest it for this exact purpose. For syntax though I think it's preferential (to be consistent with the rest of C++). – jli Mar 20 '12 at 00:06
  • @jli - I don't mind preferring `[][]` to `()`, even if it takes more effort, but I definitely prefer `()` to `.set()`. `()` at least looks closer to the mathematical notation, and offers a single consistent interface for both kinds of access. – Chris Lutz Mar 20 '12 at 00:19
3

Your matrix should provide element accessors, e.g. via operator():

template <typename T>
class Matrix
{
public:
    T & operator()(size_t i, size_t j) { return buf[i * NCols + j]; } // Example
    T const & operator()(size_t i, size_t j) const { /* same */ }

    // ...
};

Then you can say:

Matrix<bool> m(20, 20);

m(12, 15) = false;
m(8, 19) = m(1, 2) = true;
return m(0, 0);
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Thanks, Kerrek! I'm rather new to C++, can you elaborate a bit on what the template means/is? – Austin Brunkhorst Mar 19 '12 at 23:06
  • 1
    @AustinBrunkhorst: I could, but not in a comment, and no better than any good book can. Don't fear, dive in and enjoy :-) – Kerrek SB Mar 19 '12 at 23:07
  • Is there any way to accomplish this without a template? I'm trying to be consistent with what I already have and having difficulty integrating this into class. – Austin Brunkhorst Mar 19 '12 at 23:21
  • @AustinBrunkhorst: Yes, of course, just remove the template and substitute your concrete type for `T` everywhere. – Kerrek SB Mar 19 '12 at 23:29
  • I understand this, It's setting my array key values that I can't figure out with this example. I want to set values[row][column] from the operator overload. Sorry for my lack of understanding. By the way, I can't thank you enough for the help. – Austin Brunkhorst Mar 20 '12 at 00:03
  • @AustinBrunkhorst: The sad news for today is that you can't have your `values[i][j]` interface. That's not to say that you will *never* have it, but to cut the long story short, using the round-parentheses overload is going to be a lot less pain for everyone at this stage. – Kerrek SB Mar 20 '12 at 00:06
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/9066/discussion-between-austin-brunkhorst-and-kerrek-sb) – Austin Brunkhorst Mar 20 '12 at 00:07
  • @AustinBrunkhorst: Not just now - you can do it with a proxy interface class that stores a reference to your original matrix. It's not actually hard, it just requires quite a bit of extra code. – Kerrek SB Mar 20 '12 at 00:10
  • is that in response to this? `I don't think you understand what I ment. In my class, Matrix I have a 2d array of doubles, like this. double values[10][10];. On the overloaded operator (row, col) I would like to to set the variable values[][] value respectively; where [row][col]. Ending up like this: Matrix(2,5) = 15. In that examples values[2][5] would be set to 15.` – Austin Brunkhorst Mar 20 '12 at 00:14
  • @AustinBrunkhorst: Hehe, no, it was a response to the chat invite, but that was actually automatically generated :-) – Kerrek SB Mar 20 '12 at 00:15
  • Oh alright. I didn't know that was sent. Anyway, how would I go about that elaborated question? I think I'm making it hard than it really is. I just need a straight forward example of what I just described in my last comment and I will understand. – Austin Brunkhorst Mar 20 '12 at 00:19
  • @AustinBrunkhorst: Getting `m[i][j]` to work requires you to write a proxy object that represents `m[i]` and provides its own `operator[]`. It's not a big deal, maybe you can figure one out yourself. Millions of other people's matrix class implementations might also have something like that, maybe you'll see something in the wild. If this is still pertinent tomorrow we can resume this. – Kerrek SB Mar 20 '12 at 00:21
  • So I can't simply just set a variable based of the operator's parameters? We've already accomplished this for the `get` method that returns the `values[row][col]`. Why is it that much more complicated to simply set `values[row][col]` from the parameters of `Matrix(row,col) = newval;`? – Austin Brunkhorst Mar 20 '12 at 00:25
1

Use

class Matrix {

    T& operator()(size_t x, size_t y) {
        return _mat[x][y]; //Or however your datastructure works
    }

    const T& operator() (size_t x, size_t y) const {
        return _mat[x][y];
    }


};

Where T is the datatype your matrix holds. Return the data at (x,y).

Collin
  • 11,977
  • 2
  • 46
  • 60