Shachar Shemesh <[EMAIL PROTECTED]> writes:
> Hi all,
>
> Here is a small program for your viewing pleasure:
>
> > class a {
> > public:
> > explicit a(int param);
> >
> > a &operator= ( a &that );
> > };
> >
> > int main()
> > {
> > a var1(3);
> >
> > var1=a(5);
> >
> > return 0;
> > }
>
> Somewhat surprisingly, this does not compile:
> g++ -Wall -g testcompile.cc -o testcompile
> testcompile.cc: In function `int main()':
> testcompile.cc:12: error: no match for 'operator=' in 'var1 = a(5)'
> testcompile.cc:5: error: candidates are: a& a::operator=(a&)
> make: *** [testcompile] Error 1
>
> There are two things that can make it compile. One is to add a "const"
> at the "operator=" definition, and the other is to use an explicit
> variable (i.e. - not a temporary one).
>
> The reason for this failure seems to be that g++ treats temporary
> variables as consts. I see neither reason nor logic for this decision,
> however. Why can't I modify temporary variables if I so wish? Don't
> they have a well defined life span (until the end of the statement)
> for a reason?
Hi Shachar,
Compilers generate const temporaries to prevent accidental passing of
such a temporary to a function that would be able to modify its
argument. If that were allowed the programmer would be surprized
because only the compiler-generated temporary would be modified, not
the actual argument they thought they were passing.
Early versions of C++ actually allowed this (though I never saw that
in action). Apparently a lot of programmers had a surprized look on
their faces as a result.
As a result, the canonical form of operator= is
a& a::operator=(const a& rhs)
{
<whatever>
return *this;
}
i.e. it should return a non-const reference to the left-hand side of
the assignment, to allow for
x = y = z = foo = bar;
Now, this is *not* an argument why you should not be able to modify
temporaries. You should be free to modify your own temporaries if you
so wish. You should not be able to modify temporaries that are
generated by the compiler for a limited purpose, that you should not
be aware of, etc.
You can think of it in the following (formal) way: consider
x = y;
- semantically y should not be modified during the
assignment. Therefore, it should be legal to say
T x;
const T y;
...
x = y;
In practice, you are passing y to a function (x::operator=). If the
function is declared to take a reference to non-const argument code
that passes const to it should not compile since it would violate
const-correctness. The compiler keeps your sanity.
It should also make clear why your two ways of making your code
compile worked.
As an (almost unrelated) aside, the canonical form of operator=
returns a non-const reference to left-hand side. It is wrong to return
a const reference, because that would prevent assignments like
(a = b) = c;
that are perfectly legal for built-in types (however, I have never
seen a case where it would be *useful*). Contrast this with, say,
operator*:
(a * b) = c;
would be illegal for a built-in type, so operator* should return a
const reference.
--
Oleg Goldshmidt | [EMAIL PROTECTED] | http://www.goldshmidt.org
=================================================================
To unsubscribe, send mail to [EMAIL PROTECTED] with
the word "unsubscribe" in the message body, e.g., run the command
echo unsubscribe | mail [EMAIL PROTECTED]