Why this warning here?

Discussion in 'C++' started by Goran, Sep 23, 2005.

  1. Goran

    Goran Guest

    Hi all!

    I understand the rationale behind the VC++ warning 4239 (I think :))
    (warning C4239: nonstandard extension used : 'argument' : conversion
    from X to Y A reference that is not to 'const' cannot be bound to a
    non-lvalue; assigment operator takes a reference to non-const)

    However, in this situation:

    void F(X& x)

    I get it for code like this:

    F(X());

    And I find it perfectly fine. So I have to use pragma's or split this
    in two lines like this:
    { X x;
    F(x); }

    (With brackets, x gest destroyed immediately after the call; without,
    it goes out of scope later, which sometimes isn't good; but OK, this is
    not my man point)

    Anyhow... Yuck!

    Anybody has a comment on this isue? (Especially this: what "const" has
    to do with anything here!?)

    Goran.
     
    Goran, Sep 23, 2005
    #1
    1. Advertising

  2. Goran

    Guest

    Goran wrote:
    > Hi all!
    >

    [snip]

    > However, in this situation:
    >
    > void F(X& x)
    >
    > I get it for code like this:
    >
    > F(X());
    >
    > And I find it perfectly fine. So I have to use pragma's or split this
    > in two lines like this:
    > { X x;
    > F(x); }
    >

    [snip]
    >
    > Anybody has a comment on this isue? (Especially this: what "const" has
    > to do with anything here!?)


    The signature on F is an indication that F changes x, so x is a return
    value.

    F(X()) discards that return-value.

    And this is what the warning is about.
    Perhaps you should have declared F as F(X const& x)?


    /Peter
    >
    > Goran.
     
    , Sep 23, 2005
    #2
    1. Advertising

  3. Goran

    Greg Guest

    Goran wrote:
    > Hi all!
    >
    > I understand the rationale behind the VC++ warning 4239 (I think :))
    > (warning C4239: nonstandard extension used : 'argument' : conversion
    > from X to Y A reference that is not to 'const' cannot be bound to a
    > non-lvalue; assigment operator takes a reference to non-const)
    >
    > However, in this situation:
    >
    > void F(X& x)
    >
    > I get it for code like this:
    >
    > F(X());
    >
    > And I find it perfectly fine. So I have to use pragma's or split this
    > in two lines like this:
    > { X x;
    > F(x); }
    >
    > (With brackets, x gest destroyed immediately after the call; without,
    > it goes out of scope later, which sometimes isn't good; but OK, this is
    > not my man point)
    >
    > Anyhow... Yuck!
    >
    > Anybody has a comment on this isue? (Especially this: what "const" has
    > to do with anything here!?)
    >
    > Goran.


    This is the problem: F accepts a non-const reference to a variable of
    type X. So F may modify this parameter. However, the function call to F
    passes a temporary as a parameter. So F's modifications would be to a
    tempory that is then thrown away. So why call F? Or why does it accept
    a parameter? Or why pass a tempory? Something doesn't add up here.

    The most likely fix is that F does not modify x. So F's parameter
    should be declared a const reference. If it does modify x, it should be
    passed a non temporary X so that the caller will have the modified x.

    Greg
     
    Greg, Sep 23, 2005
    #3
  4. Goran

    Goran Guest

    > The signature on F is an indication that F changes x, so x is a return
    > value.


    Yep that's a good reason the warning may be desirable. Not so in my
    case

    :-((

    In my case, X is rather a "polymorphic worker class", and it may or not
    change inside X, I don't care. I just want to it passed to F to get
    polymorphic behaviour in F depending on the calling context).

    sort-of:
    BaseX
    {
    virtual f()
    }

    X1:BaseX
    {
    overridden virtual F()
    }
    X2, X3...

    and then F(BaseX&) gets called F(X1(params)), F(X2(params)),
    F(X3(params)) etc...
     
    Goran, Sep 23, 2005
    #4
  5. Goran

    Guest

    Goran wrote:
    > > The signature on F is an indication that F changes x, so x is a return
    > > value.

    >
    > Yep that's a good reason the warning may be desirable. Not so in my
    > case
    >
    > :-((


    If that is the case, you could just write the code in two steps. Not a
    big deal, is it? Anyway....
    >
    > In my case, X is rather a "polymorphic worker class", and it may or not
    > change inside X, I don't care. I just want to it passed to F to get
    > polymorphic behaviour in F depending on the calling context).

    If you don't care if the parameter gets changed, this is an indication
    that there is something wrong with your design.

    >
    > sort-of:
    > BaseX
    > {
    > virtual f()
    > }
    >
    > X1:BaseX
    > {
    > overridden virtual F()
    > }
    > X2, X3...
    >
    > and then F(BaseX&) gets called F(X1(params)), F(X2(params)),
    > F(X3(params)) etc...


    This is perfectly feasible so long as the virtual functions are const.
    This should be clear from the purpose of f.

    /Peter
     
    , Sep 23, 2005
    #5
  6. Goran

    Greg Guest

    Goran wrote:
    > > The signature on F is an indication that F changes x, so x is a return
    > > value.

    >
    > Yep that's a good reason the warning may be desirable. Not so in my
    > case
    >
    > :-((
    >
    > In my case, X is rather a "polymorphic worker class", and it may or not
    > change inside X, I don't care. I just want to it passed to F to get
    > polymorphic behaviour in F depending on the calling context).
    >
    > sort-of:
    > BaseX
    > {
    > virtual f()
    > }
    >
    > X1:BaseX
    > {
    > overridden virtual F()
    > }
    > X2, X3...
    >
    > and then F(BaseX&) gets called F(X1(params)), F(X2(params)),
    > F(X3(params)) etc...


    It's safe to assume that the caller of any function may want to know
    which parameters may change and which will not. Or to put it another
    way: which parameters are inputs, which are outputs and which are both.
    The proper use of const here helps to provide the client with that kind
    of information.

    In this case it certainly sounds like the function call to F with the
    temporary is not a mistake. So that means that there is no reason not
    to declare F's parameter, x, const. F modifying x would then be a
    legitimate error. What would be the point, given that x is not being
    returned to the caller. Well, it could turn out that F is calling a non
    const method of X's that does not actually modify the object. So
    declaring that method in X const would resolve that error. And so on
    and so forth.

    The nice thing about maintaining const-correctness in a C++ program is
    how constness cascades throughout the program. Fixing one const error
    often requires other changes in order to restore the program to a
    const-correct state. Some programmers are annoyed by this fact and will
    go the other direction and declare const as seldom as possible. But
    there is value in writing const-correct code. It is more than a mere
    nuisance. For one, it helps prevents unintended or accidental changes.
    It is also a way of documenting an API - of ensuring that a client
    understands what calling a particular function may do.

    Greg
     
    Greg, Sep 23, 2005
    #6
  7. Goran

    Goran Guest

    > > In my case, X is rather a "polymorphic worker class", and it may or not
    > > change inside X, I don't care. I just want to it passed to F to get
    > > polymorphic behaviour in F depending on the calling context).

    > If you don't care if the parameter gets changed, this is an indication
    > that there is something wrong with your design.


    Eh, easy to say... Actually, My X will change something else, that is
    the point. I wantit (well, X1, X2, etc below) to act somewhere (not
    really on itself, but on its members, and const-ness will propagate to
    them). I want that F does what it does, including doing something
    differently in different contexts, using X's polymorphism with f().

    But, as you say, there's an easy workaround...

    >
    > >
    > > sort-of:
    > > BaseX
    > > {
    > > virtual f()
    > > }
    > >
    > > X1:BaseX
    > > {
    > > overridden virtual f()
    > > }
    > > X2, X3...
    > >
    > > and then F(BaseX&) gets called F(X1(params)), F(X2(params)),
    > > F(X3(params)) etc...
     
    Goran, Sep 23, 2005
    #7
  8. Goran

    Goran Guest

    > > In my case, X is rather a "polymorphic worker class", and it may or not
    > > change inside X, I don't care. I just want to it passed to F to get
    > > polymorphic behaviour in F depending on the calling context).

    > If you don't care if the parameter gets changed, this is an indication
    > that there is something wrong with your design.


    Eh, easy to say... Actually, My X will change something else, that is
    the point. I wantit (well, X1, X2, etc below) to act somewhere (not
    really on itself, but on its members, and const-ness will propagate to
    them). I want that F does what it does, including doing something
    differently in different contexts, using X's polymorphism with f().

    But, as you say, there's an easy workaround...

    >
    > >
    > > sort-of:
    > > BaseX
    > > {
    > > virtual f()
    > > }
    > >
    > > X1:BaseX
    > > {
    > > overridden virtual f()
    > > }
    > > X2, X3...
    > >
    > > and then F(BaseX&) gets called F(X1(params)), F(X2(params)),
    > > F(X3(params)) etc...
     
    Goran, Sep 23, 2005
    #8
    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. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    979
    Mark Rae
    Dec 21, 2006
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,225
    Smokey Grindel
    Dec 2, 2006
  3. George Hester

    Try over here likely more to the point here

    George Hester, Sep 30, 2004, in forum: Javascript
    Replies:
    0
    Views:
    124
    George Hester
    Sep 30, 2004
  4. FAQ server
    Replies:
    0
    Views:
    165
    FAQ server
    Aug 10, 2006
  5. FAQ server
    Replies:
    0
    Views:
    143
    FAQ server
    Oct 7, 2006
Loading...

Share This Page