Я пишу небольшой парсер с (в настоящее время) 3 скалярными типами данных: int, float и string (char *):
typedef enum eValueType
{
E_INT, E_FLOAT, E_STRING
}
eValueType;
class CValue
{
protected:
union
{
int _i; float _f; char * _s;
};
eValueType _eType;
// ...
};
Я хотел бы перегрузить все необходимые операторы (+, -, *,/, &&, || и т.д.), Чтобы я мог легко манипулировать объектами CValue. Проблема состоит в том, что количество определяемых действий комбинаторно:
CValue operator + ( const CValue & roVal )
{
switch( roVal._eType ) {
case E_INT :
switch( this->_eType ) {
case E_INT :
break;
case E_FLOAT :
break;
case E_STRING :
break;
}
break;
case E_FLOAT :
switch( this->_eType ) {
case E_INT :
break;
case E_FLOAT :
break;
case E_STRING :
break;
}
break;
case E_STRING :
switch( this->_eType ) {
case E_INT :
break;
case E_FLOAT :
break;
case E_STRING :
break;
}
break;
}
}
Это то, что я получаю только с тремя типами, для одного оператора и без кода, который мне придется добавлять в каждом случае. Я не могу представить, если я добавлю функции, массивы и т.д.
Есть ли какой-то шаблон дизайна или метод, который я мог бы использовать для уменьшения количества кода, который я должен писать, чтобы обрабатывать каждую комбинацию типов для каждого оператора?
Спасибо :)
EDIT: Я хотел бы избежать возможностей С++ 11.
Решение состоит в том, чтобы продвинуть одну сторону (или обе, если хотите) в значение, которое может содержать всю важную информацию. Затем, после продвижения, у вас есть только одна операция для каждого типа.
Например, выражение типа 3.33 * 2
должно быть E_FLOAT * E_FLOAT. 4/2
должно быть E_INT/E_INT. И 3.33 * "3"
должен быть E_FLOAT * E_FLOAT.
E_FLOAT
, преобразуйте другой вE_FLOAT
. Если этоE_STRING
, преобразуйте его в правильное значение (целое или плавающее). Затем вы закончите сE_INT x E_INT
иE_FLOAT x E_FLOAT
.