Пишу простейший микро-компилятор, способный вычислять логические выражения. Понимаемый компилятором синтаксис (предварительно): операторы БОЛЬШЕ, МЕНЬШЕ, РАВНО, НЕ, И, ИЛИ и микро-язык запросов, берущий значения переменных из динамически создаваемой во время выполнения структуры. Навскидку набросал за полдня драфт:
class IConditionItem
{
public:
virtual ~IConditionItem()
{
}
virtual bool Evaluate() = 0;
virtual void Insert( IConditionItem * ) = 0;
};
class ICalculable : public IConditionItem
{
public:
virtual ~ICalculable()
{
}
virtual bool operator<( ICalculable const * _right ) = 0;
bool operator>( IConditionItem const * _right )
{
return( _right < this );
}
bool operator==( IConditionItem const * _right )
{
return( !(( this < _right ) && ( _right < this )) );
}
void Insert( IConditionItem * pConditionItem )
{
throw "UNIMPLEMENTED!";
}
};
class Equals : public IConditionItem
{
vector< ICalculable * > m_vArgList;
public:
Equals()
{
}
virtual bool Evaluate()
{
m_vArgList[ 0 ]->Evaluate();
m_vArgList[ 1 ]->Evaluate();
return( m_vArgList[0] == m_vArgList[1] );
}
void Insert( IConditionItem * pConditionItem )
{
ICalculable * pCalculable = dynamic_cast< ICalculable* >( pConditionItem );
if( pCalculable )
{
m_vArgList[ m_vArgList.size() ] = pCalculable;
}
}
};
class Less : public IConditionItem
{
vector< ICalculable * > m_vArgList;
public:
Less()
{
}
virtual bool Evaluate()
{
assert( m_vArgList.size() == 2 );
m_vArgList[ 0 ]->Evaluate();
m_vArgList[ 1 ]->Evaluate();
return( m_vArgList[0]->operator<( m_vArgList[1] ));
}
void Insert( IConditionItem * pConditionItem )
{
ICalculable * pCalculable = dynamic_cast< ICalculable* >( pConditionItem );
if( pCalculable )
{
m_vArgList.push_back( pCalculable );
}
else
{
// warning()
fprintf( stderr,
"Inappropriate argument type! (%s)\n",
typeid( pConditionItem ).name()
);
}
}
};
class DecimalValue;
class IntegerValue : public ICalculable
{
private:
int m_nValue;
private:
bool Evaluate()
{
// TODO: get the real value at runtime
return( !!m_nValue );
};
public:
IntegerValue() : m_nValue( 0 )
{
}
double Raw() const
{
return( m_nValue );
}
void Set( int nValue )
{
m_nValue = nValue;
}
virtual bool operator<( ICalculable const * _right );
};
class DecimalValue : public ICalculable
{
private:
double m_dblValue;
private:
bool Evaluate()
{
// TODO: get the real value at runtime
return( !!m_dblValue );
};
public:
DecimalValue() : m_dblValue( 0 )
{
}
double Raw() const
{
return( m_dblValue );
}
void Set( double dblValue )
{
m_dblValue = dblValue;
}
bool operator<( ICalculable const * _right )
{
DecimalValue const * pDecimal = dynamic_cast< DecimalValue const * >( _right );
IntegerValue const * pInteger = dynamic_cast< IntegerValue const * >( _right );
if( pDecimal )
{
return( Raw() < pDecimal->Raw() );
}
else
if( pInteger )
{
return( Raw() < pInteger->Raw() );
}
throw "UNIMPLEMENTED!";
return( false );
};
};
bool IntegerValue::operator<( ICalculable const * _right )
{
DecimalValue const * pDecimal = dynamic_cast< DecimalValue const * >( _right );
IntegerValue const * pInteger = dynamic_cast< IntegerValue const * >( _right );
if( pDecimal )
{
return( Raw() < pDecimal->Raw() );
}
else
if( pInteger )
{
return( Raw() < ( double )pInteger->Raw() );
}
throw "UNIMPLEMENTED!";
return( false );
}
class Condition
{
private:
IConditionItem * m_pConditionItem;
Condition( Condition const & );
public:
Condition( IConditionItem * pConditionItem ) :
m_pConditionItem( pConditionItem )
{
}
bool Evaluate()
{
return( m_pConditionItem->Evaluate() );
}
};
int main( int argc, char* argv[] )
{
Less myLess;
DecimalValue dblVal;
IntegerValue intVal;
dblVal.Set( 12.24 );
intVal.Set( 12 );
myLess.Insert( &dblVal );
myLess.Insert( &intVal );
Condition cond( &myLess );
bool b = cond.Evaluate();
return( 0 );
}
Вопрос в том, можно ли избавиться от dynamic_cast в реализации операторов< ?
Необходимость в каждом классе знать обо всех остальных, которые подходят для сравнения, очень утомляет, усложняет и загромождает код.