From: ark@alice.att.com (Andrew Koenig)
Newsgroups: comp.lang.c++
Subject: Re: complex classes and temporary destruction.
Date: 29 Aug 92 14:31:31 GMT
Reply-To: ark@alice.UUCP ()
Organization: AT&T Bell Laboratories, Murray Hill NJ

In article <64878@cup.portal.com> Aurelius@cup.portal.com (Mark Christian Barnes) writes:

>  But Andrew, you have changed the statement completely. The
> temporary 's+t' is no longer even being assigned to 'p'. It is
> constructed as a parameter for function (or macro) 'I'. In this
> case I would suggest that 's+t' is an auto variable with a scope
> limited to 'I'.

No, I haven't changed it at all.  I took a value and passed it to
a function that returns that same value, unchanged.  Why on earth should
doing that affect the behavior of the program?

>  I know that this means that your example will not work under
> this interpretation. Well I don't think it should. The perpetual
> problem of aliasing, to which pointers contribute, should not be
> solved by the compiler. I feel that the programmer should pay
> attention to what he/she is doing.

If programmers always paid attention to what they were doing,
any solution would work.  Indeed, there would be no need for
type checking -- just pay attention all the time and you won't
make any type errors.  Ditto for any other kind of checking,
for that matter.

Seriously, now, a large part of the discussion of lifetime of
temporaries is an attempt to avoid surprising people who don't
always pay attention to what they do.

>  In your example, an expression is evaluated and passed
> (on the stack) as the parameter to a function. The function
> 'I' returns another value of type pointer to char. There should
> not be any assumption that the parameter and the return value
> have anything in common. You, as the programmer, know that 'I'
> returns the parameter. Therefore, you should also insure that
> any parameters passed to 'I' are of the appropriate storage
> class and scope for the uses that you intend.

All right, let's look at the original example again:

	class String {
	public:
		// ...
		operator const char*();
		// ...
	};

	String operator+(const String&, const String&);

This class has a user-defined conversion operator to const char*,
but the definition of that conversion is compiled separately.  Without
inspecting it, there is no way to tell whether there is any relationship
between the result of that conversion and the object being converted.
That result might a pointer to the object's internal representation,
or it might be a pointer to a copy that was carefully stored somewhere
else.  Now we find the following:

	String a = /* some value */;
	String b = /* some other value */;

	const char* p = a+b;

Now, the expression a+b is just a shorthand for operator+(a,b), so
the last declaration above is equivalent to

	const char* p = operator+(a,b).operator const char*();

In other words, we call a function, call a member function of the
result, and assign the result of the member function to p.

On what basis do you claim that the lifetime of p should control the
lifetime of operator+(a,b)?  Remember, without reading the definitions
of operator+ and String::operator const char*, you cannot tell whether
or not there is actually any connection.  Is this any different from
the identity function in my earlier example?
-- 
				--Andrew Koenig
				  ark@europa.att.com