# Задание: Библиотека отложенных вычислений LEva

## Отложенные вычисления

Отложенные вычисления, ленивые вычисления или нестрогие вычисления (англ. lazy evaluation) — концепция, согласно которой вычисления следует откладывать до тех пор, пока не понадобится их результат. Отложенные вычисления позволяют сократить общий объём вычислений за счёт тех вычислений, результаты которых не будут использованы. Программист может описывать зависимости функций друг от друга и не следить за тем, чтобы не осуществлялось «лишних вычислений».

## Задание

Реализовать на C++ идею отложенных вычислений для типа число с плавающей точкой (класс Double) на основании предоставленных заголовочных файлов. Задание предполагает реализацию отложенных вычислений:

- с помощью деревьев абстрактных выражений (базовый класс Expression) - древовидных структур данных, описывающих суперпозицию унарных (класс UnaryExpression, в составе + и -), бинарных (класс BinaryExpression, включая +, -) выражений и выражений-переменных (класс Variable), вычисляющих свое значение (виртуальная функция Expression::eval) только при необходимости.
- и с примением умных указателей на выражения - вспомогательного класса ExpPtr, обеспечивающего подсчет ссылок на выражение и его уничтожение при достижении числа ссылок значения 0.

Реализация подсчета значения выражения должна проводить журналирование своих действий в выходной поток dout в формате:

- для переменной (Variable): (значение)
- для унарной операции (UnaryExpression): (кодu,арг)
- для бинарной операции (BinaryExpression): (кодb,арг1,арг2) Примечание: считаем, что Variable "ленива" и осуществляет журналирование в виде "(значение)" только когда ее значение понадобилось.

Реализация умного указателя на выражение должна проводить журналирование своих действий в выходной поток dout:

- '+' - увеличение числа ссылок на выражение на 1
- '-' - уменьшение числа ссылок на выражение на 1
- '~' - уничтожение выражение, связанного с умным указателем. Примечание: уменьшение последней ссылки на 1, после которого число ссылок становится равным 0 и происходит удаление выражение, должно приводить к отладочной печате в поток в виде "-~", а не только "~", т.е. сиганлизирование о последнем уменьшении числа указателей происходить должно.

## Примеры выражений и ожидаемой отладочной печати.

     Double a(1), b(0.5);
     Double c;
     c = a + b;
     cout << c;

Содержимое dout: +++++++--~+-(+b,(1),(0.5))---~-~-~

## Требования

- Отсутствие плагиата
- Прохождение предоставленных тестов
- Хороший код (хороший C++, модульность, именование, форматрирование)
- Отсылка исходных архива со всеми отчетными материалами на адрес: prak at mlab dot cs dot msu dot su

## Отчетные материалы

- Исходные тексты программы
- Тестовые сценарии (допускается использование cppunit)
- Файлы сборки (допускается использование make-фалов)
- Отчет по реализации (допускается использование документирующих комментариев doxygen), детально описывающий Вашу реализацию (функции, данные, типы).

## Вопросы, предложения, опечатки

Присылайте сюда: gerasimov at mlab dot cs dot msu dot su

Указатель Классы Функции Переменные