Помогите разобраться с заданием:
В этой задаче вам необходимо реализовать сворачивание констант в дереве (constant folding). Например, у нас есть выражение (точнее, дерево, описывающее это выражение) abs(var * sqrt(32.0 - 16.0)), на выходе мы должны получить дерево для следующего выражения abs(var * 4.0), т. е. подвыражение sqrt(32.0 - 16.0) было вычислено.
Для того, чтобы определить, что выражение (Expression) на самом деле является числом (Number), используйте оператор dynamic_cast.
Все промежуточные узлы дерева, которые вы создали, нужно освободить.
#include <cassert>
#include <string>
#include <cmath>
struct Transformer;
struct Number;
struct BinaryOperation;
struct FunctionCall;
struct Variable;
struct Expression
{
    virtual ~Expression() { }
    virtual double evaluate() const = 0;
    virtual Expression *transform(Transformer *tr) const = 0;
};
struct Transformer
{
    virtual ~Transformer() { }
    virtual Expression *transformNumber(Number const *) = 0;
    virtual Expression *transformBinaryOperation(BinaryOperation const *) = 0;
    virtual Expression *transformFunctionCall(FunctionCall const *) = 0;
    virtual Expression *transformVariable(Variable const *) = 0;
};
struct Number : Expression
{
    Number(double value);
    double value() const;
    double evaluate() const;
    Expression *transform(Transformer *tr) const;
private:
    double value_;
};
struct BinaryOperation : Expression
{
    enum {
        PLUS = '+',
        MINUS = '-',
        DIV = '/',
        MUL = '*'
    };
    BinaryOperation(Expression const *left, int op, Expression const *right);
    ~BinaryOperation();
    double evaluate() const;
    Expression *transform(Transformer *tr) const;
    Expression const *left() const;
    Expression const *right() const;
    int operation() const;
private:
    Expression const *left_;
    Expression const *right_;
    int op_;
};
struct FunctionCall : Expression
{
    FunctionCall(std::string const &name, Expression const *arg);
    ~FunctionCall();
    double evaluate() const;
    Expression *transform(Transformer *tr) const;
    std::string const &name() const;
    Expression const *arg() const;
private:
    std::string const name_;
    Expression const *arg_;
};
struct Variable : Expression
{
    Variable(std::string const name);
    std::string const & name() const;
    double evaluate() const;
    Expression *transform(Transformer *tr) const;
private:
    std::string const name_;
};
/**
 * реализйте все необходимые методы
 * если считаете нужным, то можете
 * заводить любые вспомогетльные
 * методы
 */
struct FoldConstants : Transformer
{
    Expression *transformNumber(Number const *number)
    { }
    Expression *transformBinaryOperation(BinaryOperation const *binop)
    { }
    Expression *transformFunctionCall(FunctionCall const *fcall)
    { }
    Expression *transformVariable(Variable const *var)
    {  }
};
Вот мое решение, но оно не проходит тест:
struct FoldConstants : Transformer
{
    Expression *transformNumber(Number const *number)
    {
        return new Number(number->value());
    }
    Expression *transformBinaryOperation(BinaryOperation const *binop)
    {
        Expression * a;
        Expression * b;
        if (dynamic_cast<Number*>(binop->left()->transform(this)))
            {a = binop->left()->transform(this);}
        else
            {a = (Number*)(binop->left()->transform(this));}
        if (dynamic_cast<Number*>(binop->right()->transform(this)))
            {b = binop->right()->transform(this);}
        else
            {b = (Number*)(binop->right()->transform(this));}
        BinaryOperation * c = new BinaryOperation(a, binop->operation(), b);
        return new Number(c->evaluate());
        delete c;
    }
    Expression *transformFunctionCall(FunctionCall const *fcall)
    {
        Expression * a;
        if (dynamic_cast<Number*>(fcall->arg()->transform(this)))
            {a = fcall->arg()->transform(this);}
        else
            {a = (Number*)(fcall->arg()->transform(this));}
        FunctionCall * b = new FunctionCall(fcall->name(), a);
        return new Number(b->evaluate());
        delete b;
    }
    Expression *transformVariable(Variable const *var)
    {
        return new Variable(var->name());
    }
};


