basically defining an interface where the methods may return arbitrary objects which implement a certain interface.
let's look at that IExpression interface again.
let's assume the operator+ is defined the following way:
(note that any object called XXXExpression is assumed to inherit the IExpression interface)
Code:
AnyExpression AdditionExpression::operator+ (const IExpression &_r_rhs)
{
// in case _r_rhs is just a wrapper object (e.g. AnyExpression)
// extract the a pointer to the actual object
IExpression &r_rhs = *_r_rhs.get_original_object();
if(typeid(ErrornousExpression) == typeid(r_rhs)) {
return ErrornousExpression();
}
else {
return AdditionExpression(*this, r_rhs);
}
}
now AdditionExpression may already return different types (AdditionExpression and ErrornousExpression).
what i want to do is:
Code:
void func()
{
// look up the expressions associated with some id.
// (assume this symbol table simply maps id's to expressions)
AnyExpression foo = symbol_table.lookup_associated_expression("foo");
AnyExpression bar = symbol_table.lookup_associated_expression("bar");
// foo and bar are of type AnyExpression which just wrap the "actual" expression
// (e.g. AdditionExpression, MultiplicationExpression, ...)
// so in the next line, the operator+ of the wrapped foo object is called.
AnyExpression result = foo + bar;
// i don't care the "actual" type of result. just calculate some more.
// if something is wrong with one of the operands, the implementation of
// the operator+ will handle it, maybe print an error message, and return
// an ErrornousExpression, which can be used as an operand for further
// expression objects. (all expressions must "handle" ErrornousExpression then -
// well they don't have much todo - simply return an ErrornousExpression in that case)
result = result + foo;
result = result + result;
...
// if anything wen't wrong, then result wraps an ErrornousExpression here.
symbol_table.insert("result", result);
}
i guess a good use for that would also be in parsers.
now consider this simple parser:
when the parser reads an id, it should map it to an expression.
when the parser reads a "operand1 '+' operand2", where the (non-terminal) operand is associated with an expression it should simply perform the following action: result.expression = operand1.expression + operand1.expression.
(where x.expression is an AnyExpression)
if something goes wrong here, then result.expression will simply contain an ErrornousExpression object.
in case it is some other expression, it will deal with these too.