neath@solar-1.stars.flab.Fujitsu.JUNET (08/15/89)
One of the problems that I have faced several times during the developlment of
various C++ classes is the need to return two values from some method or
function. This typically is the case where I needed to return a reference to
some object and also indicate whether the operation(s) attempted were sucessful
or not. There is direct language support for this in Lisp, but no such facility
exists in C++, or so I thought!
An expression whose value is used in any type of logical statement has its type
promoted to int before the test for zero or non-zero is made. This is because
FALSE is defined by the language to be zero and TRUE is defined to be non-zero.
It is possible in C++ to make any expresion (ie. the result of any overloaded
operator, method, or friend function) be promoted to type int just before the
test is made. This can be accomplished by either operator int() or void*().
The following example illustrates this feature. The class "positive_int" is
defined to support positive integers only. The private data section contains an
int slot for the value and a Boolean slot to maintain the state of the object.
Operations and methods defined for the class update the state slot as needed.
The inline operator void*() method casts the state slot to an int and returns
the result. The operator-= method implements subtraction for the class.
In the main() section of the program below, a positive_int object is defined
with an initial value of three. The operator-= method is invoked with a value
of five. If the result of such an operation is non-negative, the new value is
computed and a reference to the updated object is returned. However, if the
operation would result in a negative number (as in this case), the state slot
is set to FALSE and the non-updated object is returned. The void* operator is
automatically invoked by the compiler on the result of the expression. Since
the state slot was set to FALSE, the expression is evaluated as zero and the
condition fails.
#include <stream.h>
typedef enum { FALSE, TRUE } Boolean;
class positive_int {
private:
Boolean state;
int data;
public:
positive_int (int value) {
this->data = value;
this->state = TRUE;
}
positive_int& operator-= (int i) {
if (i > this->data)
this->state = FALSE;
else
this->data -= i;
return *this;
}
inline void* operator void* () {
return (void*) this->state;
}
};
int main (void) {
positive_int x(3);
if (x -= 5)
cout << "State: TRUE\n";
else
cout << "State: FALSE\n";
}
If an object has an internal state slot, then by overloading operator void*()
to behave in a manner similar to that shown above, it is possible for methods
and friend functions to perform an operation and return a reference to the
object as well as a TRUE/FALSE status. This may alleviate the need for raising
an exception and instead allow the application to handle the problem in some
other way. Incidentally, such a mechanism is used in the AT&T stream class
operator>> method to single an EOF condition while also returning a reference
to the input stream, thus facilitating statements like:
while (cin >> i) {
:::
}
Now, I mentioned above that both operator int() and operator void*() can be
overloaded to provide this functionality. For cases like the positive_int
class, I want to use operator int() to return the integer value stored in the
object so that I can mix them with other int expressions. Unfortunately, if I
overload both operator void*() and operator int(), cfront 1.2 complains with:
2 possible conversions for positive_int object in if expression
Is it possible in cfront 2.0 to overload both operator void*() and int() in the
same class to implement this type of functionality? Is this legal? Are there
alternate mechanisms for accomplishing this task?
Regards
Martin Neath <neath@dsg.ti.com>
------------------------------------------------------------------------
DISCLAIMER: As always, the opinions expressed above are strictly my own
and do not reflect those of my employer, Texas Instruments.
------------------------------------------------------------------------