Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / Managed C++ / September 2005

Tip: Looking for answers? Try searching our database.

C4239 - why here?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Goran Pusic - 23 Sep 2005 11:15 GMT
Hi all!

I understand the rationale behind the 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.
Tom Widmer [VC++ MVP] - 23 Sep 2005 12:29 GMT
> Hi all!
>
[quoted text clipped - 24 lines]
> Anybody has a comment on this isue? (Especially this: what "const" has to do
> with anything here!?)

Basically, there is a rule that a non-const reference cannot bind to an
rvalue (such as a temporary). e.g.

int i;
int*& aref = &i; //attempting to bind to an rvalue
int& bref = 5; //again, binding to an rvalue
and your example:
X& x = X(); //binding to an rvalue.

Microsoft just gives a warning, though most compilers will refuse to
compile the code entirely.

The reason for the rule is to prevent the loss of modifications to
variables. For example:

void f(int& i)
{
  i = 10;
}

double d = 0;
f(d);
//would you expect d to be 10?

Were the binding allowed, d would be converted to a temporary int, and f
would modify that temporary int, leaving d unchanged.

However, there isn't really a good reason why the binding shouldn't be
allowed when you have an exact type match (no conversions required), as
in your X example, but I think it was decided way back that the special
case wasn't really worth it, given the simple workaround.

Tom
Goran Pusic - 23 Sep 2005 12:48 GMT
> void f(int& i)
> {
[quoted text clipped - 4 lines]
> f(d);
> //would you expect d to be 10?

Yes, I see. In fact, i would expect the compiler to refuse this outright, it
just makes no sense at all! Using intrinsic type promotions on references
like this, tsk, tsk, naughty compiler... Pascal doesn't allow this! Does C#?
I hope not :-))

But, that's not my situation. I have X as 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 like this: F(X1(params)), F(X2(params)),
F(X3(params)) etc...

Goran.
Doug Harrison [MVP] - 23 Sep 2005 16:19 GMT
>But, that's not my situation. I have X as a "polymorphic worker class", and
>it may or not change inside X, I don't care. I just want to it passed to F
[quoted text clipped - 6 lines]
>and then F(BaseX&) gets called like this: F(X1(params)), F(X2(params)),
>F(X3(params)) etc...

I talked about this problem here and in the message referenced from 1997:

http://groups.google.com/group/microsoft.public.vc.stl/msg/0e2c9910ccae9bfd

The solution (kludge) I settled on was to make F take a spuriously const
X1&, which is fine unless the class stores a reference or pointer to the
object. The problem with a const X& parameter then is that it's very easy
to slip up and pass a temporary, which will be destroyed at the end of the
expression containing the function call, long before the class has finished
using it.

I once posted this as an example of a sort of built-in joke concerning the
whole rvalue/lvalue/reference behavior:

*****

http://groups.google.com/groups?selm=31bsovcdd32iedsj2utmqlmd78li40m7p6%404ax.com

struct X
{
};

void g(X&);

void f()
{
  X() = X();

  g(X() = X());

  g(X()); // No good
}

Note that above, the result of assigning one rvalue to another rvalue
is a modifiable lvalue. :)

*****

The difference between the rvalues produced by X() and int() is that the
former has member functions you can call on it, and you're allowed to call
them, including the assignment operator, which by default returns a
reference to the object assigned.

Signature

Doug Harrison
VC++ MVP

Tom Widmer [VC++ MVP] - 23 Sep 2005 16:41 GMT
>>void f(int& i)
>>{
[quoted text clipped - 9 lines]
> like this, tsk, tsk, naughty compiler... Pascal doesn't allow this! Does C#?
> I hope not :-))

Well, VC++ does at least give a diagnostic to indicate that the code has
an error - the code is "ill-formed" C++, and VC++ is reporting that fact.

> But, that's not my situation. I have X as a "polymorphic worker class", and
> it may or not change inside X, I don't care. I just want to it passed to F
[quoted text clipped - 6 lines]
> and then F(BaseX&) gets called like this: F(X1(params)), F(X2(params)),
> F(X3(params)) etc...

Perhaps F should take a const reference and f() should be a const
member? Alternatively, there is this workaround that must be used with care:

template <class T>
inline T& ref_from_temp(T const& t)
{
  return const_cast<T&>(t);
}

F(ref_from_temp(X1(params)));

Tom

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.