I need to create classes to represent expressions such as someVar=2*(5+3)^5
. For that i want to have the following classes :
class IExpression
{
public:
virtual ~IExpression( void ) { }
virtual CValue eval( const CScope & ) const = 0;
};
class CConstant : public IExpression
{
protected:
const CValue _value;
public:
virtual CValue eval( const CScope & ) const { return this->_value; }
};
class COperation : public IExpression
{
protected:
const IExpression * const _left;
const operator_e _eOper;
const IExpression * const _right;
public:
virtual ~COperation( void );
virtual CValue eval( const CScope & ) const;
};
class CVariable : public IExpression
{
protected:
const string _name;
public:
virtual CValue eval( const CScope & scope ) const { return scope.access( this->_name ); }
};
And also assume that I have a class CScope
, used by CVariable::eval()
to access variables :
class CScope
{
protected:
map<string, CValue> _mVars;
public:
inline const CValue & access( const string & name ) const;
inline CValue & access( const string & name );
};
I have a problem here. Imagine that I have an operation using an operator that requires to access the value by reference so that it can be set, like =
or +=
. For an assignment I would do :
CValue COperation::eval( const CScope & scope ) const
{
switch( this->_eOper )
{
// ...
case E_ASSIGN:
return this->_left->eval( scope ) = this->right->eval( scope );
}
}
There problem here is that this->_left->eval( scope )
, where _left
is pointing to a CVariable
, is going to return a copy of the CValue
identified by the name of that variable, and the assignment isn't going to work.
I could change the signature of the method eval() to make it return a CValue &
, but that would cause a problem because in the case of a COperation, the result of the operation is a temporary variable that gets destroyed as soon as COperation::eval()
returns.
Do you have an idea about how I could do that?