Understanting assignments

Discussion in 'C++' started by et al., Aug 25, 2010.

  1. et al.

    et al. Guest

    Hi all! I am following the C++ operator overloading guidelines (*) in
    order to create a simple matrix class, with all standard operators
    (sum, difference, and so on). Everything worked until I tried to use
    the assignment operator! As with the guideline, I started implementing
    the compound assignments, then I use them exactly as in the guide to
    create an operator (first operator=*, and next using it for defining
    operator*).

    What I am battling with this compilation error:

    error: no match for 'operator=' in 'p = #'obj_type_ref' not supported
    by dump_expr#<expression error>(((matrix&)(& o)))'
    note: candidates are: virtual matrix& matrix::eek:perator=(matrix&)

    within this simple assignment:

    matrix p, a, o;
    // Do something with "a" and "o", then:
    p = a * o; // <==== BAM! Compilation error!

    My class "matrix" defines all the operators I need as in the guideline:

    class matrix {
    // ...
    virtual matrix& operator=(matrix& src);

    virtual matrix& operator+=(matrix& src);
    virtual matrix& operator-=(matrix& src);
    virtual matrix& operator*=(double src);
    virtual matrix& operator*=(matrix& src);

    virtual matrix operator+(matrix& src);
    virtual matrix operator-(matrix& src);
    virtual matrix operator*(double src);
    virtual matrix operator*(matrix& src);

    virtual bool operator==(matrix& src);
    virtual bool operator!=(matrix& src);
    // ...
    };

    However, if I change a little the assignment using the compound ones,
    it works perfectly:


    matrix p, a, o;
    // Do something with "a" and "o", then:
    p = a;
    p *= o;
    // It works like a charm


    I am sorry I can't understand the error, I am still learning! Can you
    point me in the right direction?

    Thanks & cheers!


    (*) URL:
    http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html
    et al., Aug 25, 2010
    #1
    1. Advertising

  2. et al.

    SG Guest

    On 25 Aug., 17:22, Christian Hackl wrote:
    >
    > Oh, and there's one more thing I overlooked before. The functions
    > themselves should be declared const, too, because they don't change
    > their own matrix.
    >
    > matrix const operator+(matrix const& src) const;

    ^^^^^
    This const is debatable. I never felt the need to return objects by
    const value. And with C++0x coming along you're effectivly disabling
    move semantics with this.

    > ...
    > bool operator==(matrix const& src) const;


    Also, for symmetry reasons the above two operators could be replaced
    by free functions.

    Cheers!
    SG
    SG, Aug 25, 2010
    #2
    1. Advertising

  3. et al.

    SG Guest

    On 25 Aug., 18:31, Christian Hackl wrote:
    > SG ha scritto:
    >
    > > On 25 Aug., 17:22, Christian Hackl wrote:

    >
    > >> matrix const operator+(matrix const& src) const;

    > >          ^^^^^
    > > This const is debatable. I never felt the need to return objects by
    > > const value.

    >
    > How else do you prevent (a * b) = c?
    >
    > This is also an item in Effective C++.


    Yes. I have that book (3rd edition). I like it. But this is one of the
    very few rules I don't agree with. And I'm sure that if a C++0x-aware
    edition came out, it would say something different.

    If you want this code fragment to be ill-formed, you also have the
    option of adding a ref qualifier to your assignment operator in C++0x.

    Anyhow, for about 10 years, I'm using programming languages that have
    == as comparison operator. I really can't recall the last time (if
    ever) I made this mistake you're referring to.

    > I've not studied C++0x move semantics enough. But surely there's a way
    > to have both the efficiency gained by move semantics and the prevention
    > of (a * b) = c.


    Yes:

    class foo {
    ...
    foo& operator=(foo const&) &;
    ...
    };


    Cheers!
    SG
    SG, Aug 25, 2010
    #3
  4. On 8/25/2010 12:48 PM, Christian Hackl wrote:
    > Pete Becker ha scritto:
    >
    >> On 2010-08-25 12:31:47 -0400, Christian Hackl said:
    >>
    >>> SG ha scritto:
    >>>
    >>>> On 25 Aug., 17:22, Christian Hackl wrote:
    >>>>> matrix const operator+(matrix const& src) const;
    >>>> ^^^^^
    >>>> This const is debatable. I never felt the need to return objects by
    >>>> const value.
    >>> How else do you prevent (a * b) = c?

    >>
    >> Don't write it. Seriously.

    >
    > But what if I don't want others (i.e. users of my class) to write it, or
    > not to write it by accident?


    Accident? Seriously? What, a typo when you intended to write

    (a * b) == c

    ? With matrices? Strongly doubt that. As Pete says, you're spending
    time worrying about something that almost never happens.

    >> You can spend your time solving non-problems, or you can do real work.

    >
    > Since when does adding "const" to a function signature waste time that
    > could be spent for "real" work?


    Any time you do that to the code you inherit (and that doesn't contain
    those const qualifiers), you'd not be doing real work, you'd be wasting
    everybody's time.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Aug 25, 2010
    #4
  5. et al.

    SG Guest

    On 25 Aug., 19:46, Pete Becker wrote:
    >
    > Oh, I see: this is the = instead of == typo. Easily caught by unit
    > tests. Still way down on my list.


    Since one would want to use it in a boolean context, it won't even
    compile unless the type in quetion is also convertible to something
    "bool-like". I don't think that the matrix class needs to be
    convertible to a "bool-like".

    Cheers!
    SG
    SG, Aug 25, 2010
    #5
  6. et al.

    Kai-Uwe Bux Guest

    Christian Hackl wrote:

    > Victor Bazarov ha scritto:
    >
    >> On 8/25/2010 12:48 PM, Christian Hackl wrote:
    >>> Pete Becker ha scritto:
    >>>
    >>>> On 2010-08-25 12:31:47 -0400, Christian Hackl said:
    >>>>
    >>>>> SG ha scritto:
    >>>>>
    >>>>>> On 25 Aug., 17:22, Christian Hackl wrote:
    >>>>>>> matrix const operator+(matrix const& src) const;
    >>>>>> ^^^^^
    >>>>>> This const is debatable. I never felt the need to return objects by
    >>>>>> const value.
    >>>>> How else do you prevent (a * b) = c?
    >>>> Don't write it. Seriously.
    >>> But what if I don't want others (i.e. users of my class) to write it, or
    >>> not to write it by accident?

    >>
    >> Accident? Seriously? What, a typo when you intended to write
    >>
    >> (a * b) == c

    >
    > No, I was thinking of typos like when someone intended to write a = (b *
    > c).


    I don't recall an instant of screwing up that way. Maybe, I was just lucky;
    but I have a feeling that this kind of typo might be rather rare.

    >> Any time you do that to the code you inherit (and that doesn't contain
    >> those const qualifiers), you'd not be doing real work, you'd be wasting
    >> everybody's time.

    >
    > Changing existing files which are used by everyone else on the project
    > is a different story. I was more thinking of the case when a class is
    > designed and you are writing new code to be added to the project.


    Actually, that would depend on the coding guidelines for the project. If
    there is established precedence that operators return by value rather than
    by const value, I would go with the precedence. After all, users of my
    matrix class may try things like

    (B*C).swap( A ); // simulating a move to A

    to speed up performance in bottlenecks. The point is that coding guidelines
    and precedence shape rational expectations, which one might not want to
    break within a project.


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Aug 25, 2010
    #6
  7. et al.

    Öö Tiib Guest

    On 25 aug, 22:52, Christian Hackl <> wrote:
    > Pete Becker ha scritto:
    >
    > > Oh, I see: this is the = instead of == typo. Easily caught by unit
    > > tests.

    >
    > If it's a library used by someone else, then your own unit tests cannot
    > catch the typo.
    >
    > I'm quite surprised that such a harmless [*] hint, backed by a
    > recommendation in of the most recommended C++ books, would cause so much
    > discussion on the grounds that it's not important enough :)
    >
    > [*] except of the problem with move semantics, which I had not been
    > aware of before


    Sorry, i do not care really about issue itself, up to designer of
    interface and its contract IMO. Just particular detail makes me
    wonder... how does it compile? for example:

    Matrix a, b, c;
    if ( ( a * b ) = c )
    {
    // blah-blah
    }

    It should say you cannot convert a Matrix to bool. Or is there some
    safe bool? What does it indicate? if ( a ) sounds similarily
    nonsensical about Matrix.
    Öö Tiib, Aug 25, 2010
    #7
  8. On 8/25/2010 3:52 PM, Christian Hackl wrote:
    > Pete Becker ha scritto:
    >
    >> Oh, I see: this is the = instead of == typo. Easily caught by unit tests.

    >
    > If it's a library used by someone else, then your own unit tests cannot
    > catch the typo.
    >
    >
    > I'm quite surprised that such a harmless [*] hint, backed by a
    > recommendation in of the most recommended C++ books, would cause so much
    > discussion on the grounds that it's not important enough :)
    >
    >
    > [*] except of the problem with move semantics, which I had not been
    > aware of before


    When I encounter code

    SomeType const function(arguments...);

    then the first thing that springs into my mind is, "it's a typo and the
    implementor forgot to add either * or & before the function name..." It
    is idiomatic to see

    SomeType function(arguments...);

    or

    SomeType const& function(arguments...);

    The recommendations to write anything different require (in my book
    anyway) that the reason better be important. Harmless hint? No, it's a
    step away from very common idioms, you see.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Aug 25, 2010
    #8
  9. On 8/25/2010 4:48 PM, Öö Tiib wrote:
    > On 25 aug, 22:52, Christian Hackl<> wrote:
    >> Pete Becker ha scritto:
    >>
    >>> Oh, I see: this is the = instead of == typo. Easily caught by unit
    >>> tests.

    >>
    >> If it's a library used by someone else, then your own unit tests cannot
    >> catch the typo.
    >>
    >> I'm quite surprised that such a harmless [*] hint, backed by a
    >> recommendation in of the most recommended C++ books, would cause so much
    >> discussion on the grounds that it's not important enough :)
    >>
    >> [*] except of the problem with move semantics, which I had not been
    >> aware of before

    >
    > Sorry, i do not care really about issue itself, up to designer of
    > interface and its contract IMO. Just particular detail makes me
    > wonder... how does it compile? for example:
    >
    > Matrix a, b, c;
    > if ( ( a * b ) = c )
    > {
    > // blah-blah
    > }
    >
    > It should say you cannot convert a Matrix to bool. Or is there some
    > safe bool? What does it indicate? if ( a ) sounds similarily
    > nonsensical about Matrix.


    Somebody might design the class that calculates some kind of
    characteristic of the matrix to be used in shortcuts like those. I am
    not advocating it, but don't dismiss it simply because you're not going
    to use it. Correctness of the interface is in the eye of the beholder.
    Of course, just like with other things, implicit conversions are
    dangerous and better avoided, blah blah... All falls into the style
    category, as far as I'm concerned.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Aug 25, 2010
    #9
  10. et al.

    Öö Tiib Guest

    On 26 aug, 00:35, Christian Hackl <> wrote:
    > Maybe the influence of Meyers' books on my mind has been too strong, but
    > to me, "SomeType operator+(SomeType const &)" is what looks "strange",
    > and not the const version. YMMV.



    Yeah, matter of taste. For example the one that looks most familiar to
    me is:

    class SomeType
    {
    // ...
    friend SomeType operator+(const SomeType&, const SomeType&);
    // ...
    }

    That is because i always try to write binary operators (besides =) as
    non-member non-friends and if i can't, as friends. why to argue? There
    are only very tiny differences.
    Öö Tiib, Aug 25, 2010
    #10
  11. et al.

    James Kanze Guest

    On Aug 25, 9:54 pm, Victor Bazarov <> wrote:

    [...]
    > When I encounter code


    > SomeType const function(arguments...);


    > then the first thing that springs into my mind is, "it's
    > a typo and the implementor forgot to add either * or & before
    > the function name..." It is idiomatic to see


    > SomeType function(arguments...);


    > or


    > SomeType const& function(arguments...);


    > The recommendations to write anything different require (in my
    > book anyway) that the reason better be important. Harmless
    > hint? No, it's a step away from very common idioms, you see.


    I understand this point of view, but a lot depends on who's
    doing the recommendation. Scott Meyers is a "recognized
    authority"; the fact that he recommends it in "Effective C++"
    means that it is something you should have seen, or will see, or
    should expect to see. (This isn't argument by authority, but
    rather simple recognition of the fact that Scott Meyers' books
    have influenced many people, so you will see code following his
    recommendations.)

    The other issue is coding conventions. Within a given program,
    all code should be written according to the same conventions.
    If you see
    SomeType const function(...);
    once, and everywhere else, it's without the const, then the most
    obvious explination is that the programmer forgot the &. If
    every returned value of class type has a const, then it's almost
    certainly the house style, and not an oversight.

    FWIW: I don't use the const, despite Scott's recommendation.
    I'd gotten into the habit of not using it before reading Scott's
    recommendation, and in practice, I don't find writing = for ==
    a problem. You do it once or twice the first couple of weeks,
    and then you learn. And of course, user defined types don't
    normally convert implicitly to bool anyway, unless you're
    abusing conversions. So it's not really a problem. (A more
    useful requirement would be that operator++ and operator-- are
    always a free functions, rather than members, so you can only
    call them on lvalues.) But it wouldn't bother me if
    I encountered code which did systematically, and if I were to
    work for a company where adding the const were house rules, I'd
    adapt.

    --
    James Kanze
    James Kanze, Aug 26, 2010
    #11
  12. * James Kanze, on 26.08.2010 10:38:
    > On Aug 25, 9:54 pm, Victor Bazarov<> wrote:
    >
    > [...]
    >> When I encounter code

    >
    >> SomeType const function(arguments...);

    >
    >> then the first thing that springs into my mind is, "it's
    >> a typo and the implementor forgot to add either * or& before
    >> the function name..." It is idiomatic to see

    >
    >> SomeType function(arguments...);

    >
    >> or

    >
    >> SomeType const& function(arguments...);

    >
    >> The recommendations to write anything different require (in my
    >> book anyway) that the reason better be important. Harmless
    >> hint? No, it's a step away from very common idioms, you see.

    >
    > I understand this point of view, but a lot depends on who's
    > doing the recommendation. Scott Meyers is a "recognized
    > authority"; the fact that he recommends it in "Effective C++"
    > means that it is something you should have seen, or will see, or
    > should expect to see. (This isn't argument by authority, but
    > rather simple recognition of the fact that Scott Meyers' books
    > have influenced many people, so you will see code following his
    > recommendations.)


    Scott wrote that advice before moving from rvalues was recognized as important.

    With Andrei's Mojo effort Andrei declared Scott's earlier advice dead (very
    publicly, in DDJ). Simply put, new programming paradigms influence how we best
    use old constructs.

    Ad I'm 99.95% certain that Scott agrees with that, that that old way is dead
    now, considering move semantics with C++0x.


    [snip]

    Cheers,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
    Alf P. Steinbach /Usenet, Aug 26, 2010
    #12
  13. et al.

    et al. Guest

    On 2010-08-25 17:18:36 +0200, Christian Hackl <> said:

    > et al. ha scritto:
    >
    >> error: no match for 'operator=' in 'p = #'obj_type_ref' not supported
    >> by dump_expr#<expression error>(((matrix&)(& o)))'
    >> note: candidates are: virtual matrix& matrix::eek:perator=(matrix&)
    >>
    >> within this simple assignment:
    >>
    >> matrix p, a, o;
    >> // Do something with "a" and "o", then:
    >> p = a * o; // <==== BAM! Compilation error!

    >
    > That's because you don't pass the argument of operator= by const&, so
    > the temporary, nameless matrix created by "a * o" cannot be assigned to
    > p.


    So, I can then use safely const, but I have a simple problem when
    accessing an element.

    In one subclass, I re-implemented the at() member: this is for a banded
    symmetric matrix, so I store only part of the matrix, leaving the rest
    as 0.0. My member is as follows:

    double& at(unsigned int r, unsigned int c)

    One thing that I couldn't do is returning 0.0 by reference, so I added
    a double member "zero" that the constructor sets to 0.0, and if needed
    I return that in at(). However, this is contrary to the fact that I
    would like zero to be "const"! Do you know how I can avoid this ugly
    implementation with a "const" ?



    >> My class "matrix" defines all the operators I need as in the guideline:
    >>
    >> class matrix {
    >> // ...
    >> virtual matrix& operator=(matrix& src);

    >
    > First of all, remove "virtual" from all operators. You usually should
    > not combine operator overloading with OOP. Besides, you surely won't
    > derive from matrix, do you?


    Well, I am, actually. I am learning through exercises, so I am deriving
    "vector" from the "matrix" class, and a "symmatrix" (banded and
    symmetric) one. Both subclasses re-implement some methods, but no
    operators that I can think of. Why do you recommend that operators
    should never be virtual? (Anyway, I removed them)

    >> virtual matrix operator+(matrix& src);
    >> virtual matrix operator-(matrix& src);
    >> virtual matrix operator*(double src);
    >> virtual matrix operator*(matrix& src);

    >
    > Again, remove virtual, add const. Additionally, the return value of
    > these functions should be "matrix const", rather than "matrix".
    > Otherwise, statements such as the following will not result in a
    > compiler error (as they should):
    >
    > (a * o) = p;
    >
    > matrix const operator+(matrix const& src);
    > etc.


    Allright, I begin to see why this is recommendable!


    >> However, if I change a little the assignment using the compound ones,
    >> it works perfectly:
    >>
    >>
    >> matrix p, a, o;
    >> // Do something with "a" and "o", then:
    >> p = a;
    >> p *= o;
    >> // It works like a charm

    >
    > That's because no temporary, nameless objects are involved.
    >
    > If you correctly add const to the function signatures, all those
    > problems and inaccuracies will go away.



    Thank you very much! I am now using const references without any pain! :)


    Only one question: I am now implementing the const member at() for
    accessing an element. First I implemented the "reference" at() that
    allows me to modify elements of the matrix:

    double& matrix::at(unsigned int r, unsigned int c)

    and then, I implemented another const member at(), calling the first one:

    double const matrix::at(unsigned int r, unsigned int c) const

    Is it safe to do this? I think so, since when in the second I call just
    "return at(r, c);", it should create a temporary double. Am I right or
    completely wrong?

    Thanks & cheers!
    et al., Aug 26, 2010
    #13
  14. et al.

    Jorgen Grahn Guest

    On Thu, 2010-08-26, James Kanze wrote:
    ....
    > [...] in practice, I don't find writing = for ==
    > a problem. You do it once or twice the first couple of weeks,
    > and then you learn.


    Perhaps I'm spoiled by g++, but it warns me if I use a = b in a
    boolean context. I think I get to see that warning once a year or so
    -- but I often write sloppily, relying on compilation and sometimes
    unit tests to catch most errors, and then review before checking in to
    version control.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Aug 26, 2010
    #14
  15. et al.

    James Kanze Guest

    On Aug 26, 10:14 am, "Alf P. Steinbach /Usenet" <alf.p.steinbach
    > wrote:
    > * James Kanze, on 26.08.2010 10:38:
    > > On Aug 25, 9:54 pm, Victor Bazarov<> wrote:


    > > [...]
    > > I understand this point of view, but a lot depends on who's
    > > doing the recommendation. Scott Meyers is a "recognized
    > > authority"; the fact that he recommends it in "Effective
    > > C++" means that it is something you should have seen, or
    > > will see, or should expect to see. (This isn't argument by
    > > authority, but rather simple recognition of the fact that
    > > Scott Meyers' books have influenced many people, so you will
    > > see code following his recommendations.)


    > Scott wrote that advice before moving from rvalues was
    > recognized as important.


    Which could easily be yesterday. Most practicing C++
    programmers have never heard of moving from rvalues. Precisely
    because it isn't important to them. I'd heard about it, because
    I followed the evolving standards more than most, but I hadn't
    encountered a context where it was important before a year ago.
    It very much depends on what you're application is doing, and
    for most applications, it's completely irrelevant. (Even for
    applications where it's relevant, there are generally acceptable
    work-arounds. It's a useful addition to C++, for some
    applications, but it's hardly a world shaker.)

    > With Andrei's Mojo effort Andrei declared Scott's earlier
    > advice dead (very publicly, in DDJ). Simply put, new
    > programming paradigms influence how we best use old
    > constructs.


    > Ad I'm 99.95% certain that Scott agrees with that, that that
    > old way is dead now, considering move semantics with C++0x.


    Which is neither here nor there. As I said, this is one piece
    of Scott's advice I never actually practiced, but others may
    have, and that's not a problem either. Perhaps his advice would
    be different today---I can understand the argument with regards
    to move semantics, even in cases where they aren't currently
    important. But the fact remains that many people do follow his
    previous practice, and it's not a problem either. (The only
    problem is if you stop being consistent.)

    --
    James Kanze
    James Kanze, Aug 28, 2010
    #15
  16. et al.

    SG Guest

    On 26 Aug., 11:14, Alf P. Steinbach wrote:
    >
    > Scott wrote that advice before moving from rvalues was recognized as important.
    >
    > With Andrei's Mojo effort Andrei declared Scott's earlier advice dead (very
    > publicly, in DDJ). Simply put, new programming paradigms influence how we best
    > use old constructs.
    >
    > Ad I'm 99.95% certain that Scott agrees with that, that that old way is dead
    > now, considering move semantics with C++0x.


    I even have a recent quote on that:

    Scott Meyers wrote:
    > Balog Pal wrote:
    > > I recall some SM advices to retuen const string from functions
    > > instead of string to cover the same set of problems. Never liked
    > > that advice, did not follow it, did not see it followed, and NO
    > > problems related to hat are in my attention whatsoever.

    >
    > And this SM no longer offers that advice, because returning const
    > rvalues disables move semantics for the temporaries thus generated.
    >
    > Scott


    [taken from a comp.std.c++ thread: "Modifying rrefs to constants"]

    Cheers!
    SG
    SG, Sep 9, 2010
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Neil Zanella
    Replies:
    2
    Views:
    975
    Neil Zanella
    Oct 26, 2003
  2. Nicolas Matringe
    Replies:
    9
    Views:
    716
    Mike Treseler
    Jun 14, 2004
  3. Gary Thorpe

    Using aggregates for assignments

    Gary Thorpe, Jun 14, 2004, in forum: VHDL
    Replies:
    4
    Views:
    689
  4. ALuPin

    Back-Annotate Assignments

    ALuPin, Oct 20, 2004, in forum: VHDL
    Replies:
    1
    Views:
    1,774
    Ben Twijnstra
    Oct 20, 2004
  5. Alex Rast
    Replies:
    3
    Views:
    654
Loading...

Share This Page