Why this warning here?

G

Goran

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.
 
P

peter.koch.larsen

Goran said:
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
 
G

Greg

Goran said:
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
 
G

Goran

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

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...
 
P

peter.koch.larsen

Goran said:
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
 
G

Greg

Goran said:
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
 
G

Goran

In my case, X is rather a "polymorphic worker class", and it may or not
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...
 
G

Goran

In my case, X is rather a "polymorphic worker class", and it may or not
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...
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top