From: Aurelius@cup.portal.com (Mark Christian Barnes)
Newsgroups: comp.lang.c++
Subject: Re: complex classes and temporary destruction.
Date: Sat, 29 Aug 92 12:07:38 PDT
Organization: The Portal System (TM)
Distribution: world
  <23563@alice.att.com> <64821@cup.portal.com> <23578@alice.att.com>
  <64878@cup.portal.com> <23587@alice.att.com>

Andrew Koenig replies:

|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.

 This is quite true. In addition, I don't think it should matter
what the conversion method returns. Since, as you point out below,
it is invoked after the storage class of operator+(a,b) should have
already been determined in this instance.

|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.
 ^^^^^^
 The "result" is the temporary value in question. What is the
storage class of the return *value* of operator+(a,b)? Does it
construct a new object of type String? We don't know. If it
does not, then there's not a temporary in your example anyways.

 If operator+(a,b) does, in fact, construct a temporary of type
String, then the compiler could determine its storage class,
perhaps based upon the storage class of the context to which
it is applied. In this case it is not an assignment to 'p',
directly. First the operator const char*(), of our new,
potential temporary, must be evaluated. The result of that
evaluation is assigned 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

 So what have we got? Well we've made an assignment to 'p'. We
expect that assignment to remain valid for the life of 'p'. It
would seem that both 'p' and this unnamed "temporary" object
of class String could require the same storage class.
Furthermore, it might be correct to destruct both of them at
the same point. Of course, all kinds of nasty things must be
cleared up whenever 'p' is assigned to other pointers, etc,
which may propogate the lifetime of the unnamed "temporary".

 I see that, in a way, we've done something to undermine
the integrity of the String object by allowing it to
represent itself as a const char*. Should we now overload the
global const char* operator= to cooperate with this conversion?
If so, then what scheme shall be used? Reference counting?
Smart Pointers, etc, etc, ...?

			Regards, Aurelius@cup.portal.com
Newsgroups: comp.lang.c++