Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Is f() lvalue?

Reply
Thread Tools

Is f() lvalue?

 
 
Michael Ovetsky
Guest
Posts: n/a
 
      10-31-2004

Consider:

int g(){int b=1; return b;}

int main()
{
int d=2;
g()=d;
}


gcc compiler fails to compile it with 'non-lvalue in assignment' error
message, which I would expect.

However the following code happily compiles and executes:

struct A {int a;};
A f(){A b={1}; return b;}

int main()
{
A c ={2};
f()=c;
}


Does it mean that f() is lvalue if f returns struct or class object, but
not lvalue if f returns built-in type or incorrect implementation of
C++ standard by gcc is one to blame?

Thanks,

Michael


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use (E-Mail Removed) ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


 
Reply With Quote
 
 
 
 
marco.wahl@gmail.com
Guest
Posts: n/a
 
      10-31-2004
> int g(){int b=1; return b;}
> g()=d;


> struct A {int a;};
> A f(){A b={1}; return b;}
>
> int main()
> {
> A c ={2};
> f()=c;
> }


> Does it mean that f() is lvalue if f returns struct or class object,

but
> not lvalue if f returns built-in type ....?


Yes, I think so.

I think a returned object is a lvalue (some say: value with location).
Obviously the returned object must have a location.
The int return-value of g is not a lvalue. It's just 1.

--
Marco

 
Reply With Quote
 
 
 
 
Andrey Tarasevich
Guest
Posts: n/a
 
      10-31-2004
Michael Ovetsky wrote:

> Consider:
>
> int g(){int b=1; return b;}
>
> int main()
> {
> int d=2;
> g()=d;
> }
>
>
> gcc compiler fails to compile it with 'non-lvalue in assignment' error
> message, which I would expect.
>
> However the following code happily compiles and executes:
>
> struct A {int a;};
> A f(){A b={1}; return b;}
>
> int main()
> {
> A c ={2};
> f()=c;
> }
>
>
> Does it mean that f() is lvalue if f returns struct or class object, but
> not lvalue if f returns built-in type or incorrect implementation of
> C++ standard by gcc is one to blame?
>


There's nothing wrong with the compiler. In both cases the returned
object is not an lvalue. The difference between the two is that in the
first case you are using built-in assignment operator and in the second
case you are using user-defined assignment operator (which in this case
is provided by the compiler as 'A& A:perator=(const A&)').

The built-in assignment operator requires an lvalue on the left-hand
side. That's why you get the error message.

The user-defined assignment operator has no such requirement and the
code compiles fine.

--
Best regards,
Andrey Tarasevich

 
Reply With Quote
 
Michael Ovetsky
Guest
Posts: n/a
 
      11-01-2004
>There's nothing wrong with the compiler. In both cases the returned
>object is not an lvalue. The difference between the two is that in

the
>first case you are using built-in assignment operator and in the

second
>case you are using user-defined assignment operator (which in this

case
>is provided by the compiler as 'A& A:perator=(const A&)').


It still seems to me that gcc considers function call that returns
structure an lvalue.

The following code won't compile with "non-lvalue in unary `&'"
message.

int g(){int b=1; return b;}
int main()
{
&g();
}

However the following code will compile (albeit with "taking address
of temporary" warning)and execute:

struct A {int a;};
A f(){A b={1}; return b;}
int main()
{
&f();
}

I don't think that gcc uses user-defined A* operator&() in this case,
it just takes address of an object.

Michael Ovetsky
 
Reply With Quote
 
Tom Widmer
Guest
Posts: n/a
 
      11-01-2004
On 1 Nov 2004 09:23:08 -0800, http://www.velocityreviews.com/forums/(E-Mail Removed) (Michael Ovetsky)
wrote:

>>There's nothing wrong with the compiler. In both cases the returned
>>object is not an lvalue. The difference between the two is that in

>the
>>first case you are using built-in assignment operator and in the

>second
>>case you are using user-defined assignment operator (which in this

>case
>>is provided by the compiler as 'A& A:perator=(const A&)').

>
>It still seems to me that gcc considers function call that returns
>structure an lvalue.
>
>The following code won't compile with "non-lvalue in unary `&'"
>message.
>
>int g(){int b=1; return b;}
>int main()
>{
> &g();
>}
>
>However the following code will compile (albeit with "taking address
>of temporary" warning)and execute:


The code is not well-formed, and the compiler is conforming in that it
outputs a diagnostic as required by the standard.

>struct A {int a;};
>A f(){A b={1}; return b;}
>int main()
>{
> &f();
>}
>
>I don't think that gcc uses user-defined A* operator&() in this case,
>it just takes address of an object.


Right, but the code isn't legal, since f() is an rvalue. You could
make it legal by explicitly overloading operator&, so you're back to
calling a member function on an rvalue, which is perfectly legal.

Tom
 
Reply With Quote
 
Andrey Tarasevich
Guest
Posts: n/a
 
      11-01-2004
Michael Ovetsky wrote:
> ...
> It still seems to me that gcc considers function call that returns
> structure an lvalue.


No, it doesn't.

> The following code won't compile with "non-lvalue in unary `&'"
> message.
>
> int g(){int b=1; return b;}
> int main()
> {
> &g();
> }
>
> However the following code will compile (albeit with "taking address
> of temporary" warning)and execute:
>
> struct A {int a;};
> A f(){A b={1}; return b;}
> int main()
> {
> &f();
> }
>
> I don't think that gcc uses user-defined A* operator&() in this case,
> it just takes address of an object.


The second example is also ill-formed. You are right, in this case the
built-in operator '&' is used. And it is used illegally, since the
result of 'f' is not an lvalue.

GCC compiler implements a moderately popular language extension that
allows this code to compile and issues a warning to inform you about
that fact. It is a little surprising that GCC still compiles this code
in '-ansi -pedantic' mode (although issuing a warning is already enough
to satisfy the standard requirement concerning diagnostic messages).
Comeau Online compiler rejects the code with an error message.

--
Best regards,
Andrey Tarasevich
 
Reply With Quote
 
James Dennett
Guest
Posts: n/a
 
      11-01-2004

Michael Ovetsky wrote:

> Consider:
>
> int g(){int b=1; return b;}
>
> int main()
> {
> int d=2;
> g()=d;
> }
>
>
> gcc compiler fails to compile it with 'non-lvalue in assignment' error
> message, which I would expect.
>
> However the following code happily compiles and executes:
>
> struct A {int a;};
> A f(){A b={1}; return b;}
>
> int main()
> {
> A c ={2};
> f()=c;
> }
>
>
> Does it mean that f() is lvalue if f returns struct or class object, but
> not lvalue if f returns built-in type or incorrect implementation of
> C++ standard by gcc is one to blame?


It's an rvalue (not an lvalue) in either case, but you *can*
assign to an rvalue of class type (because assignment in that
case is just syntactic sugar for a call to the operator=
member function, and member functions can be used on rvalues).

This is one reason why in some situations it makes sense to
return UDT values as consts, whereas that is nonsensical for
builtin types.

-- James

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use (E-Mail Removed) ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

 
Reply With Quote
 
Alberto Barbati
Guest
Posts: n/a
 
      11-01-2004

Michael Ovetsky wrote:
> Does it mean that f() is lvalue if f returns struct or class object, but
> not lvalue if f returns built-in type or incorrect implementation of
> C++ standard by gcc is one to blame?
>


gcc is conformant, but the reason is not the one you describe.

First of all, 3.10/5 clearly says that "The result of calling a
function that does not return a reference is an rvalue." So f() returns
an rvalue in both cases (basic type and class type).

It's true that 5.17/1 says "[Assigment operators] requires a modifiable
lvalue as their left operand" but that statement only applies to the
built-in assignment operator, i.e. it's true only for basic types. For
class types 5.17/4 takes precedence: "Assignment to objects of a class
is defined by the copy assignment operator (12.8, 13.5.3)"

Because of 13.5.3, when f() is of class type f() = expr is interpreted
as f().operator=(expr). Here's the quirk: you *can* invoke a member
function even on an rvalue. Thus the expression f() = expr is legal.

I know that it's not very intuitive, but that's how it is. A sometimes
useful idiom is to return a const T instead of a T, as in that case the
compiler won't be able to call operator= because it operates only on
non-const objects.

HTH,

Alberto

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use (E-Mail Removed) ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

 
Reply With Quote
 
Arijit
Guest
Posts: n/a
 
      11-01-2004

GCC is right. What happens is in case of struct, the struct's assignment
operator (implicitly defined) gets called. So, the line f()=c actually
reads: c.operator =(f()); which is okay and compiles.

BTW, if I used a C compiler for this, will f()=c compile ?

-Arijit

Michael Ovetsky <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
> Consider:
>
> int g(){int b=1; return b;}
>
> int main()
> {
> int d=2;
> g()=d;
> }
>
>
> gcc compiler fails to compile it with 'non-lvalue in assignment' error
> message, which I would expect.
>
> However the following code happily compiles and executes:
>
> struct A {int a;};
> A f(){A b={1}; return b;}
>
> int main()
> {
> A c ={2};
> f()=c;
> }
>
>
> Does it mean that f() is lvalue if f returns struct or class object, but
> not lvalue if f returns built-in type or incorrect implementation of
> C++ standard by gcc is one to blame?
>


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use (E-Mail Removed) ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

 
Reply With Quote
 
Ben Hutchings
Guest
Posts: n/a
 
      11-01-2004

Michael Ovetsky wrote:
<snip>
> However the following code happily compiles and executes:
>
> struct A {int a;};
> A f(){A b={1}; return b;}
>
> int main()
> {
> A c ={2};
> f()=c;
> }
>
>
> Does it mean that f() is lvalue if f returns struct or class object, but
> not lvalue if f returns built-in type or incorrect implementation of
> C++ standard by gcc is one to blame?


Neither. There is no prohibition against calling non-const members of
rvalues of class-type, so in general you can assign to them. For this
reason some authors recommend qualifying return types with 'const' if
they are class-types.

--
Ben Hutchings
Who are all these weirdos? - David Bowie, about L-Space IRC channel #afp

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use (E-Mail Removed) ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

 
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




Advertisments