Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Why this warning here?

Reply
Thread Tools

Why this warning here?

 
 
Goran
Guest
Posts: n/a
 
      09-23-2005
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.

 
Reply With Quote
 
 
 
 
peter.koch.larsen@gmail.com
Guest
Posts: n/a
 
      09-23-2005

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.


 
Reply With Quote
 
 
 
 
Greg
Guest
Posts: n/a
 
      09-23-2005
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

 
Reply With Quote
 
Goran
Guest
Posts: n/a
 
      09-23-2005
> 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...

 
Reply With Quote
 
peter.koch.larsen@gmail.com
Guest
Posts: n/a
 
      09-23-2005

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

 
Reply With Quote
 
Greg
Guest
Posts: n/a
 
      09-23-2005

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

 
Reply With Quote
 
Goran
Guest
Posts: n/a
 
      09-23-2005
> > 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...


 
Reply With Quote
 
Goran
Guest
Posts: n/a
 
      09-23-2005
> > 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...


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
why why why why why Mr. SweatyFinger ASP .Net 4 12-21-2006 01:15 PM
findcontrol("PlaceHolderPrice") why why why why why why why why why why why Mr. SweatyFinger ASP .Net 2 12-02-2006 03:46 PM
warning C4267 and warning C4996 B. Williams C++ 17 10-27-2006 09:41 PM
Warning: WARNING Charles Computer Support 7 08-16-2005 09:07 PM
Re: A code fix for MSVC warning C4267 (64-bit compatibility warning,e.g. Boost Spirit) Pete Becker C++ 0 02-10-2005 01:13 PM



Advertisments