C++ operator overloading WTF



  • I found this code in a tutorial on matrix math. No wonder there are so many WTFs on this site, people are being taught them!

    Matrix Matrix::operator*(const Matrix& b){
    // New matrix
    float c[16];

    c[0] = (values[0]*b.values[0]) + (values[4]*b.values[1]) + (values[8]*b.values[2]) + (values[12]*b.values[3]);

    ... bunch of lines ...

    c[15] = (values[3]*b.values[12]) + (values[7]*b.values[13]) + (values[11]*b.values[14]) + (values[15]*b.values[15]);

    set_values(c);
    return *this;
    }



  • Meh...forum software strikes again.



    Matrix Matrix::operator*(const Matrix& b){

    // New matrix

    float c[16];



    c[0] = (values[0]*b.values[0]) + (values[4]*b.values[1]) + (values[8]*b.values[2]) + (values[12]*b.values[3]);

    ... bunch of lines ...

    c[15] = (values[3]*b.values[12]) + (values[7]*b.values[13]) + (values[11]*b.values[14]) + (values[15]*b.values[15]);



    set_values(c);

    return *this;

    }



  • Took me sometime to find the WTF. Do you mean that little = missing after operator*?



  • It assigns the result of the operation to itself.



  • Yes..

    A bit odd indeed.

    And that its accessed in one long row? That's a bit odd to me too...

    Though, it could be a 1x16 "matrix". ;)



  • @Ulvhamne said:

    Yes..

    A bit odd indeed.


    I wouldn't merely qualify this of "odd". It doesn't respect the operator's semantics and could cause someone using the class to shoot themselves badly in the foot. Operator overloading is supposed to make your life easier, not hellish. And setting such a trap in such a well-known mathematical operation as matrix product is especially bad. At least if it was an operator perverted for some bizarre usage; people would expect to enter a WTF minefield.

    Also, the operator is not const even though it should be. So a perfectly legal multiplication of two const matrices won't compile (making it easier to find the WTF), and a perfectly legal aswell multiplication where the left matrix is not const will lead to fucked up side-effects and lots of fun for the poor user of that crap to find out why his calculations are all fucked up.

    And that its accessed in one long row? That's a bit odd to me too...


    It's probably a 4*4 matrix stored lineraly in memory. Not the most beautiful thing around, and writing a matrix multiplication using hard coded indices instead of a set of constants to map a name containing the line and column to the index is unecessarily obfiscated and make it way easier to get it wrong.



  • maratcolumn has a point, though. Perhaps it was just the implementation of operator*= and the author forgot the =, which would promote this from WTF to unfortunate mis-spelling bug.



  • @Zlodo said:

    Also, the operator is not const even though it should be. So a perfectly legal multiplication of two const matrices won't compile (making it easier to find the WTF), and a perfectly legal aswell multiplication where the left matrix is not const will lead to fucked up side-effects and lots of fun for the poor user of that crap to find out why his calculations are all fucked up.

    That's actually how I discovered it. My calculations were coming out sort of close to what they should be, but off in bizarre ways. Eventually I multiplied with a const matrix on the left and found the WTF.

    @Zlodo said:

    maratcolumn has a point, though. Perhaps it was just the implementation of operator*= and the author forgot the =, which would promote this from WTF to unfortunate mis-spelling bug.

    The tutorial called it the "times operator". I think the author just didn't bother to test his code on two multiplications in a row before posting it.



  • @Zlodo said:



    I wouldn't merely qualify this of "odd". It doesn't respect the operator's semantics and could cause someone using the class to shoot themselves badly in the foot. Operator overloading is supposed to make your life easier, not hellish. And setting such a trap in such a well-known mathematical operation as matrix product is especially bad. At least if it was an operator perverted for some bizarre usage; people would expect to enter a WTF minefield.

    Also, the operator is not const even though it should be. So a perfectly legal multiplication of two const matrices won't compile (making it easier to find the WTF), and a perfectly legal aswell multiplication where the left matrix is not const will lead to fucked up side-effects and lots of fun for the poor user of that crap to find out why his calculations are all fucked up.

    Yes, then again, understatements are popular in sweden. I've had to work with classes that did these wonderful things with the operators. *Brr*
    Maybe I should give the autor my own matrix class? Naah. ;)

    @Zlodo said:


    It's probably a 4*4 matrix stored lineraly in memory. Not the most beautiful thing around, and writing a matrix multiplication using hard coded indices instead of a set of constants to map a name containing the line and column to the index is unecessarily obfiscated and make it way easier to get it wrong.

    Yeah. But, loop unrolling is so efficient!



  • @Zlodo said:

    @Ulvhamne said:
    Yes..

    A bit odd indeed.

    I wouldn't merely qualify this of "odd". It doesn't respect the operator's semantics and could cause someone using the class to shoot themselves badly in the foot. Operator overloading is supposed to make your life easier, not hellish.

    Not in C++ though. The widespread misuse of operator overloading in C++ (because people learned it in school, thought it was therefore "the cool thing to do" and used it everywhere, especially where they shouldn't have) is what led to the "Operator Overloading is Bad" backlash and java not having them (but for the Sun guys of course)



  • What or where is this widespread misuse of operator overloading everyone keeps jabbering on about?! I've been using C++ professionally for eight years now and I've very seldom indeed seen this ugly mythological beast. It reeks of the dragons everyone knew existed in the dark ages.

    Having gone through innumerable C++ dumps I have found many horrors. But principally all these have had to do with structure, algorithms or simply inept programmers; and I've found the very same horrors in C, Java and several other language's source too.



  • The should of course be "source in other languages". Why, oh why, can't we edit posts?!



  • @Mikademus said:

    The should of course be "source in other languages". Why, oh why, can't we edit posts?!




    Has to be some strange overloaded operator. ;)



  • One more thing to nag is the naming scheme. Don't they teach people to name their member variables distinctively any more? One thing I hate, when having to read just a snippet of code is when I have to stop to think "Where does this variable  (values) come from and which scope it does belong to?"




  • @Mikademus said:

    What or where is this widespread misuse of operator overloading everyone keeps jabbering on about?!


    stdout << "wtf";



  • @Mikademus said:

    What or where is this widespread misuse of operator overloading everyone keeps jabbering on about?!


    About nowhere. This is usual anti-C++ FUD.



  • @Zlodo said:

    @Mikademus said:
    What or where is this widespread misuse of operator overloading everyone keeps jabbering on about?!


    About nowhere. This is usual anti-C++ FUD.

    I think the people that made those horrible operators got tired of pointers and went to Java and Co. ;)
    Im currently making a game... And some of the programmers cant handle const, much less pointers. Some of the code is really strange. Though, they dont do that weird thing called operator overloading... (Or whatever)... And I'm really glad they dont.



  • @Zlodo said:

    @Mikademus said:
    What or where is this widespread misuse of operator overloading everyone keeps jabbering on about?!


    About nowhere. This is usual anti-C++ FUD.

    You mean like this one by the eminently nicked "Irrelevent"?:
    @Irrelevant said:
    stdout << "wtf";



  • @Ulvhamne said:

    I think the people that made those horrible operators got tired of pointers and went to Java and Co. ;)

    Im currently making a game... And some of the programmers cant handle const, much less pointers. Some of the code is really strange. Though, they dont do that weird thing called operator overloading... (Or whatever)... And I'm really glad they dont.

    Same here. I'm working on a codebase where a lot of very horribe things have been done without operator overloading.
    There have been people working on this codebase in the past doing things like this:

    void somefunction()
    {
        try
        {
           // some code

           if( something )
              goto error;

           // some more code

           if( something_else )
              throw;
        }
        catch(...)
        {
            goto error;
        }

        if( 0 )
        {
           error:
              // error handling code
        }

        // Some cleanup code
    }

    Yet for some reason, AFAIK they never redefined operators others than legitimate streaming or arithmetic operations (wish they did too, there are places using manual reference counting instead of smart pointers).

    But you just know that you can't possibly design a language that could force someone like this to write proper code. That's why I'm not fan of languages throwing out useful features like operator overloading on the grounds that it is possible to write crappy code using it.

    @Mikademus said:
    You mean like this one by the eminently nicked "Irrelevent"?:


    Indeed.



  • @Zlodo said:

    @Ulvhamne said:
    I think the people that made those horrible operators got tired of pointers and went to Java and Co. ;)

    Im currently making a game... And some of the programmers cant handle const, much less pointers. Some of the code is really strange. Though, they dont do that weird thing called operator overloading... (Or whatever)... And I'm really glad they dont.

    Same here. I'm working on a codebase where a lot of very horribe things have been done without operator overloading.
    There have been people working on this codebase in the past doing things like this:

    void somefunction()
    {
        try
        {
           // some code

           if( something )
              goto error;

           // some more code

           if( something_else )
              throw;
        }
        catch(...)
        {
            goto error;
        }

        if( 0 )
        {
           error:
              // error handling code
        }

        // Some cleanup code
    }

    Yet for some reason, AFAIK they never redefined operators others than legitimate streaming or arithmetic operations (wish they did too, there are places using manual reference counting instead of smart pointers).

    But you just know that you can't possibly design a language that could force someone like this to write proper code. That's why I'm not fan of languages throwing out useful features like operator overloading on the grounds that it is possible to write crappy code using it.

    Well, I agree on that part about forbidding operators merely because one can make some pretty odd and unexpected functionality with it. The people that would do so generally manage that by mere horribly named functions and some Terrific code like your example. ;) ME, for instance just had a long argument about objects having directions or not in a 3D space.
    And I'm crying everytime I see things like:

    // Removed the const because they did not work.
    void setRotation(/*const*/ Vector3/*&*/ rotationAxis, /*const*/ float angle)

     



  • @Ulvhamne said:

    And I'm crying everytime I see things like:

    // Removed the const because they did not work.
    void setRotation(/*const*/ Vector3/*&*/ rotationAxis, /*const*/ float angle)


    Heh. Here, when they feel like screwing up constness, they tend to use const_cast. Sometimes on the this pointer.


  • Agreed, operator overloading is a pain.  I have to admit that it makes a nice, intuitive shorthand, but it also can cause total confusion when it doesn't behave in the obvious fashion.  Take the Matrix class I made for a school project.  I needed three different fashions of doing matrix multiplication, so what did I shorten them to?  Why *, %, and /, of course.  It was carefully documented, but still I shudder to think of what would have happened had anyone wanted to actually USE that class.
    -FM



  • @FunnyMan said:

    Agreed, operator overloading is a pain.  I have to admit that it makes a nice, intuitive shorthand, but it also can cause total confusion when it doesn't behave in the obvious fashion.  Take the Matrix class I made for a school project.  I needed three different fashions of doing matrix multiplication, so what did I shorten them to?  Why *, %, and /, of course.  It was carefully documented, but still I shudder to think of what would have happened had anyone wanted to actually USE that class.
    -FM

    don't kick yourself. Code written for school projects is not expected to ever be used in the real world.
    Of course a lot of it gets regurgitated in realworld projects with little or no change anyway...



  • @FunnyMan said:

    Agreed, operator overloading is a pain.  I have to admit that it makes a nice, intuitive shorthand, but it also can cause total confusion when it doesn't behave in the obvious fashion.  Take the Matrix class I made for a school project.  I needed three different fashions of doing matrix multiplication, so what did I shorten them to?  Why *, %, and /, of course.  It was carefully documented, but still I shudder to think of what would have happened had anyone wanted to actually USE that class.
    -FM


    Agreed with who? You can confuse the liveing daylights out of any programmer by creating methods with names not really relating to their mechanics. As I stated above, after many years developing in C++ I have exceedingly seldom seen any of the alledged atrocities attributed to operator overloading, nor in fact even many minor ones. It is a chimera, an urban FUD legend of programmers, like Zlodo phrased it.

    Seriously, most of your learning code is utter bollocks, you messed up overloading your operators just as you messed up writing proper code of other kinds too. That is irrelevant and not indicative of anything exept you having once been a coder neonate. Write shoddy production code in serious houses and you get the boot, regardless whether overloaded operators or vanilla methods.


Log in to reply