Topic: return type of operator=
Author: jimad@microsoft.com (Jim Adcock)
Date: 03 Nov 92 19:52:40 GMT Raw View
In article <1992Oct31.025229.6520@cs.brown.edu> sdm@cs.brown.edu (Scott Meyers) writes:
|Is the return type of operator= an lvalue?
No.
|In particular, if a, b, and c are of built-in type, is this legal?
|
| (a = b) = c;
No, it is an error. If (a = b) were an lvalue the same
as "a" then "a" would be being accessed twice for modification in one
expression, which in turn is an unconstrained error.
|I couldn't find an answer in the ARM,
My answers are based on the ANSI-C spec, under the optimistic assumption that
some day the ANSI/ISO-C++ spec will contain equivalently detailed language about
what kinds of errors can occur in programs, and what actions compilers
can or cannot perform as a result of those errors.
|My goal is to determine the correct type for user-defined operator=. If
|the return type is to be an lvalue, then for a class C, the return type
|should be C&. However, if the return value is not to be an lvalue, then
|op= should return a const C&. Two years ago I thought const C& was the
|right type, but since then I've become convinced that C& is better. Now
|doubt has surfaced in my mind again, and I'd like to put the matter to
|rest.
The "right" thing to do is to return a value, not a reference. Given
the infrequent use of the implied value of an assignment operation,
many C++ programmers are lothe to return by value. In which case
returning a const reference might be an acceptable hack. You might return
void instead in cases where programmers shouldn't reasonably expect
to use a side-effect value of assignment. Don't return a non-const reference.
This would further confuse users about the illegality of modifying a
variable multiple times in one expression.
Author: davisonj@en.ecn.purdue.edu (John M Davison)
Date: Wed, 4 Nov 92 05:19:14 GMT Raw View
In article <1992Nov03.195240.14360@microsoft.com> jimad@microsoft.com (Jim Adcock) writes:
>In article <1992Oct31.025229.6520@cs.brown.edu> sdm@cs.brown.edu (Scott Meyers) writes:
>|Is the return type of operator= an lvalue?
>
>No.
Jim is mistaken; the built-in types return an lvalue in C++ (except for
bit-field assignment, which I don't know about offhand).
>|In particular, if a, b, and c are of built-in type, is this legal?
>|
>| (a = b) = c;
>
>No, it is an error. If (a = b) were an lvalue the same
>as "a" then "a" would be being accessed twice for modification in one
>expression, which in turn is an unconstrained error.
It is not an error. ((a=b)=c) is equivalent to (a=c), except for side
effects, of course.
>My answers are based on the ANSI-C spec
In Standard C, = returns an rvalue. In C++, = returns an lvalue.
Stroustrup talks about this in the "Lvalues" section of "The Evolution
of C++: 1985 to 1989". I quote:
"Note that the default definition of assignment of
an X as a call of
X& operator=(const X&)
makes assignment of Xs produce an lvalue. For uniformity,
this rule has been extended to assignments of built-in
types. By implication, +=, -=, *=, etc. now also produce
lvalues. So -- again by implication -- does prefix ++ and
-- (but not the postfix versions of these operators).
"In addition, the comma and ?: can also produce
lvalues...."
>The "right" thing to do is to return a value, not a reference.
>...Don't return a non-const reference.
Return a non-const reference. C++ does it with its built-in types.
--
John Davison
davisonj@ecn.purdue.edu
Author: jimad@microsoft.com (Jim Adcock)
Date: 05 Nov 92 19:02:57 GMT Raw View
In article <1992Nov4.051914.25983@en.ecn.purdue.edu> davisonj@en.ecn.purdue.edu (John M Davison) writes:
|In article <1992Nov03.195240.14360@microsoft.com> jimad@microsoft.com (Jim Adcock) writes:
|>In article <1992Oct31.025229.6520@cs.brown.edu> sdm@cs.brown.edu (Scott Meyers) writes:
|>|Is the return type of operator= an lvalue?
|>
|>No.
|
| Jim is mistaken; the built-in types return an lvalue in C++ (except for
|bit-field assignment, which I don't know about offhand).
|
|>|In particular, if a, b, and c are of built-in type, is this legal?
|>|
|>| (a = b) = c;
|>
|>No, it is an error. If (a = b) were an lvalue the same
|>as "a" then "a" would be being accessed twice for modification in one
|>expression, which in turn is an unconstrained error.
|
| It is not an error. ((a=b)=c) is equivalent to (a=c), except for side
|effects, of course.
I continue to disagree -- with a *tiny* retraction. The ref manual says
that (a = b) is a *value* which is a lvalue. The ref manual DOES NOT specify
that the lvalue is a reference to a. Thus I continue to maintain that
((a=b)=c)
has to either NOT modify a in the outer assignment, rather instead modifying
an unnamed temporary, or alternately a is being accessed twice in one expression
for modification, which continues to be an unconstrained error. In either
case it is certainly NOT correct to say that ((a=b)=c) is the same as (a=c)
except for side effect. Either ((a=b)=c) is NOT the same as (a=c) or
alternately its an unconstrained error.
|>My answers are based on the ANSI-C spec
|
| In Standard C, = returns an rvalue. In C++, = returns an lvalue.
|
| Stroustrup talks about this in the "Lvalues" section of "The Evolution
|of C++: 1985 to 1989". I quote:
|
| "Note that the default definition of assignment of
| an X as a call of
|
| X& operator=(const X&)
|
| makes assignment of Xs produce an lvalue. For uniformity,
| this rule has been extended to assignments of built-in
| types. By implication, +=, -=, *=, etc. now also produce
| lvalues. So -- again by implication -- does prefix ++ and
| -- (but not the postfix versions of these operators).
|
| "In addition, the comma and ?: can also produce
| lvalues...."
Note in none of this did the author of one of the base documents specify
*what* object the lvalue was referring to. By continuing *not* to make
that specification the situation remains the same as in ANSI-C where accessing
a variable more than once in an expression for modification remains
ill-defined. You may get either or both side-effects or neither or something
else entirely.
|>The "right" thing to do is to return a value, not a reference.
|>...Don't return a non-const reference.
|
| Return a non-const reference. C++ does it with its built-in types.
I continue to disagree. It is extremely unlikely that any C++ programmer
is going to use that non-const reference in a legal manner. Do them a
favor up front and at least make it const.
I wonder if this whole mess shouldn't be added to the list of non-modifiable
lvalues? Or are these issues going to be eventually clarified by adding clear
constraints to the eventual ANSI/ISO-C++ spec?
Author: sdm@cs.brown.edu (Scott Meyers)
Date: Sat, 31 Oct 1992 02:52:29 GMT Raw View
Is the return type of operator= an lvalue? In particular, if a, b, and c
are of built-in type, is this legal?
(a = b) = c;
I couldn't find an answer in the ARM, and cfront accepts this, while g++
rejects it.
My goal is to determine the correct type for user-defined operator=. If
the return type is to be an lvalue, then for a class C, the return type
should be C&. However, if the return value is not to be an lvalue, then
op= should return a const C&. Two years ago I thought const C& was the
right type, but since then I've become convinced that C& is better. Now
doubt has surfaced in my mind again, and I'd like to put the matter to
rest.
Scott
-------------------------------------------------------------------------------
What do you say to a convicted felon in Providence? "Hello, Mr. Mayor."
Author: bs@alice.att.com (Bjarne Stroustrup)
Date: 31 Oct 92 13:48:12 GMT Raw View
sdm@cs.brown.edu (Scott Meyers @ Brown University Department of Computer Science) writes
> Is the return type of operator= an lvalue?
yes
> In particular, if a, b, and c are of built-in type, is this legal?
>
> (a = b) = c;
yes
> I couldn't find an answer in the ARM, and cfront accepts this, while g++
> rejects it.
The third sentence of the first paragraph of 5.17 of the reference manual
(pg 79 of the ARM, pg 506 Of my 2nd edition):
The result of the assignment operator is ...; the result is
and lvalue.
Author: ark@alice.att.com (Andrew Koenig)
Date: 31 Oct 92 14:10:08 GMT Raw View
In article <1992Oct31.025229.6520@cs.brown.edu> sdm@cs.brown.edu (Scott Meyers) writes:
> Is the return type of operator= an lvalue? In particular, if a, b, and c
> are of built-in type, is this legal?
> (a = b) = c;
Yes.
> My goal is to determine the correct type for user-defined operator=. If
> the return type is to be an lvalue, then for a class C, the return type
> should be C&.
It should be C&. The general rule is that any built-in operator that
returns one of its operands will do so as an lvalue if the operand is.
(except ?:, which yields an lvalue only if both the alternatives are
lvalues of the same type).
The thing that motivated this decision was a member function like this:
T& T::fun() {
// ...
return (*this = /*some value*/);
}
The person who wrote this thought that
return (*this = /*some value*/);
would mean the same as
*this = /*some value*/;
return *this;
but in a function that returns a T&, it means the same only if = yields a T&.
This is a strict extension from C: there is no way to write a strictly
conforming C program that is capable of detecting whether = returns an
lvalue.
--
--Andrew Koenig
ark@europa.att.com