9

I have created a class Matrix which basically represents a mathematical matrix. In order to use a scalar-matrix multiplication, I have overloaded the * operator as:

Matrix Matrix::operator*(double scalar) const
{
    Matrix result(*this);
    result *= scalar;
    return result;
}

To make the operator work from left as well, I have used:

Matrix operator*(double a, const Matrix &M)
{
  return M * a;
}

Given Matrix M and double s, M * s works fine but s * M gives me an error:

Error C2677: binary * : no global operator found which takes type Matrix (or there is no acceptable conversion)

while the IDE shows me the error: "no operator * matches these operands".

Any idea what could be the problem?


Edit: That was a stupid mistake! I hadn't declared the operator in the header and the compiler couldn't see the declaration! So sorry for that...

Alborz
  • 93
  • 1
  • 6
  • 1
    And full example code. Didn't you define a return type for your first operator definition? – Sebastian Jun 19 '13 at 18:26
  • @Sebastian, That was a typo and I corrected it. I'm getting this error in my code where I have mIIdevCon = mIIcon - one3*mIIvol where mIIdevCon, mIIcon, mIIvol are Matrix objects and one3 is "const double Matrix::one3 = 1.0/3.0;" – Alborz Jun 19 '13 at 18:34
  • Can't reach ideone to put up an example, but your code sure compiles locally for me with just a simple double*Matrix. Could you create a simple reproducible sample? – Joachim Isaksson Jun 19 '13 at 18:37

1 Answers1

8

When I follow the recommendations given in the FAQ entry on operator overloading (especially the paragraph on binary arithmetic operators) I can not reproduce your error.

This compiles just fine for me:

struct M {
    M& operator*= (float f) {
        // multiply this by f
        return *this;
    }
};

inline M operator* (M m, float f) {
    m *= f;
    return m;
}

inline M operator* (float f, M m) {
    return m * f;
}

int main() {
    M m;
    float f;
    m * f;
    f * m;
}

I hope this helps. If not, please provide more code.

Community
  • 1
  • 1
moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • @legends2k because you need a copy anyway to return the value (it can be optimized when you pass by value: copy elision). – moooeeeep Jun 19 '13 at 18:41
  • Which happens only when the matrix has heap-allocated resources which is unlikely for a matrix (array of floats). – legends2k Jun 19 '13 at 18:44
  • @legends2k A matrix implementation which doesn’t use heap-allocated memory is downright idiotic. – Konrad Rudolph Jun 19 '13 at 18:46
  • 3
    @KonradRudolph: Why is it idiotic, assuming the size of the matrix is constant (or defined by a template parameter), and you don't want to bother with reference counting to avoid copying? – Sebastian Jun 19 '13 at 18:48
  • 1
    @KonradRudolph: `glm` uses array of floats for example, I don't understand why it's idiotic. – legends2k Jun 19 '13 at 18:48
  • @Sebastian Because it trashes your stack. Stack space is very, very limited. You don’t use it for potentially huge matrices. – Konrad Rudolph Jun 19 '13 at 18:50
  • 2
    @KonradRudolph: Perhaps you've not programmed 3D graphics, I can tell many more graphics math libraries which use plain arrays or `std::array` for storing vectors and matrices. – legends2k Jun 19 '13 at 18:50
  • 2
    @legends2k Sure, 3x3 matrices. Don’t claim that this is the most common use-case. I am working with 100x100 (and more) matrices. glm also won’t use stack-allocated arrays for those. – Konrad Rudolph Jun 19 '13 at 18:52
  • 1
    @KonradRudolph: I'm not claiming anything here, it's just that how 3x3 isn't the most common so is 100x100. But declaring `a matrix not heap-allocated is down right idiotic` is just being arrogant making assumptions that 100x100 are the most commonly used ones. – legends2k Jun 19 '13 at 18:53
  • @moooeeeep My code is almost the same as what you have written above. The only difference is the way I defined the operator*. Which I have used "Matrix Matrix::operator*(double scalar) const" for the first implementation of operator* and "Matrix operator*(double a, const Matrix &M)" for the second one. Do you think this makes a difference? And many thanks for your answer! – Alborz Jun 19 '13 at 18:54
  • @legends2k Well you are certainly making some very unlikely assumptions here. Nothing in OP’s code indicates that the size of the matrix is even a compile-time constant (of course that could be a simplification, but going from that to saying “heap-allocated resources … is unlikely for a matrix” goes bit far, won’t you say?) My comment was maybe a bit too quick itself but I was going from the general case since I lacked any more specific information. – Konrad Rudolph Jun 19 '13 at 18:55
  • @Alborz: Why don't you try? – Sebastian Jun 19 '13 at 18:55
  • @KonradRudolph: I didn't give any answer making any assumption I was just commenting to moooeeep's answer asking for more clarification, when you barged-in uninvited :) – legends2k Jun 19 '13 at 18:58
  • @Sebastian Regarding your original comment: reference counting to avoid copying will be *cheaper* than copying stack-allocated memory. With stack-allocated matrices you cannot avoid copying. Furthermore, modern C++ can often use moving rather than copying which makes this a *very* cheap operation, no reference counting needed (but it doesn’t work for purely stack-allocated memory). – Konrad Rudolph Jun 19 '13 at 18:58
  • @legends2k I’m just quoting you. You *said* heap-allocation was unlikely. – Konrad Rudolph Jun 19 '13 at 18:58
  • 1
    @Alborz of course it makes a difference. If `const` are involved it can be very tricky to get it right. If you are looking for a deeper diagnosis, you need to provide more code, e.g., turn your code into a minimum compilable example that still reproduces the error. – moooeeeep Jun 19 '13 at 19:01
  • @moooeeeep I changed the code and it's working now, However I still don't understand why it didn't work! I know you need my code to give your judgement but since the code is working now and reducing the code to a minimum workable example requires time, I hope you don't mind to finish the question right here. Thanks for your help... – Alborz Jun 19 '13 at 19:22
  • Thanks everybody for your comments and thank you @stakx for editing my original question. – Alborz Jun 19 '13 at 19:23
  • Well, I'm so sorry! That was really a stupid mistake! I hadn't declared the "Matrix operator*(double a, const Matrix &V)" in my header file. So my main code couldn't see the declaration of overloading operator. I'm so sorry... – Alborz Jun 19 '13 at 19:45