Re: returning lvalue in C vs C++



* Alan Johnson wrote, on 31.03.2006 11:14:
Alf P. Steinbach wrote:
int main(void)
{
struct thing t = {20};
int y = (f() = t).x;


This is invalid in both C and C++.

Why is this invalid in C++?

The expression 'f() = t'.

I can't answer the "why" better than I already have (for that ask in [comp.std.c++]), except to note that allowing it would make it impossible to emulate built-in types via the class mechanism, but as to the "how" it is invalid:

The C++ 1998 standard, §3.10/5, "The result of calling a function that does not return a reference is an rvalue."

§3.10/2 states that rvalue expressions of class or cv-qualified type refer to objects, and notes (note 47) that "Expressions such as invocations of constructors and of functions that return a class type refer to objects, and the implementation can invoke a member function upon such objects, but the expressions are not lvalues".

Then §3.10/4 notes that some built-in operators expect lvalue operands, and gives as example, "Example: built-in assignment operators all expect their left hand operands to be lvalues".

So, §3.10./5 says the result of f() is an rvalue, §3.10/4 says the built-in assignment operator requires an lvalue (and so does §5.17/1), and the built-in assignment operator is IMO what's being used above.

There is a loop-hole because the whole of §3.10/4 is formulated as a "[Note: ...]", which indicates non-normative text. There is also a loop-hole because §5.17, after discussing how assignment operators require lvalues, and a bit more, mentions that assignment to objects of class types is defined by the copy assignment operator. It does that to bring in the recursive definition of assignment, and it does mention at the start that "all" assignment operators require lvalues, "All require a modifiable lvalue as their left operand" (where again there is a loop-hole because what's meant is assignment expressions, not the operators themselves or operator calls, but that isn't spelled out but is implicit in that otherwise one would have a contradiction). Finally there is a loop-hole in that "built-in" is nowhere explictly defined.

But such formal loop-holes are all over the place, the standard being very far from perfect, which means some amount of interpretation is required: my interpretation is to accept the text and the intention conveyed by the text, for if it had no meaning or was simply wrong, then the text shouldn't be in the standard in the first place, and the standard would then be very incomplete regarding this issue. Simply put, all assignment expressions require lvalue left operands, §5.17/1, that's what the "l" in lvalue is all about. And the result of call of a function that does not yield a reference, is not an lvalue, §3.10/5.


If I understand correctly, f() returns an rvalue of class type, and therefore you can call the operator= member for it.

Yes, you can, but not via an assignment expression.


For what it's worth, both g++ and Comeau think it is valid.

Yes, and Comeau behaves inconsistently with regard to assignment to a member (try the expression "f().x = 666")"; as I see it, and I don't think there's any way around it short of declaring §3.10/4 as incorrect (it /is/ formally non-normative), both compilers are in flagrant violation of the standard for this code.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
.



Relevant Pages

  • Re: C questions
    ... Richard Heathfield wrote: ... unary & requires an lvalue only when it is applied ... Reading email is like searching for food in the garbage, ...
    (comp.lang.c)
  • Re: Order of precedence - In combination with = and without =
    ... It does yield an lvalue in C++ and I can't ... assignment operators, but I think you've got the rationale ...
    (comp.lang.c)
  • Re: what exactly does the operator |= ???
    ... 2.10 Assignment Operators and Expressions. ... page numbers in different English printings of a given edition of K&R ... Chapter 3, on Control Flow, ...
    (comp.lang.c)
  • Re: Listener_Con.ksh[42]: allow: not found
    ... Unfortunately the standard does not spell it out clearly. ... once you realise that the shell is required to support ... assignment operators in arithmetic expansions, ... names in C can be used as variables in arithmetic expansions. ...
    (comp.unix.shell)
  • Re: what exactly does the operator |= ???
    ... It's entitled "Assignment operators and expressions", ... Before learning to program, ... adjust your email clients. ...
    (comp.lang.c)