Средства Forest действительно не претендуют быть столь же универсальными как базовые конструкции языка C++. Это искусственные макросы и классы некоторой более высокоуровневой концепции, предназначеннные для решения определенных задач в рамках определенных условий и соглашений применения. В то же время, они не настолько ограничивают применение средств языка, что про конструкцию try catch можно совсем забыть при необходимости анализа типа ошибок.Побуждением написания средств была также необходимость написания программ, которые не рассматривают ошибки реализации, шаг влево или вправо в исходных данных или условиях протекания вычислительных процессов как попытку к бегству, и не выдают столь осмысленное для оператора сообщение Runtime Error at this a very biutefull address. А как показала моя практика разработки сложных программных комплексов, происходить иногда могут совершенно непредвиденные ошибки в совершенно непредвиденных местах, сколько бы программер не старался предусмотреть все варианты развития событий. Такие уж у меня руки кривые.
В целом вроде методология себя оправдала, позволив достаточно шаблонно подходить к программированию множества проверок вычислительного процесса, а не только исходных данных. При этом комплексно решаются задачи вывода детального отчета о типе и месте происхождения ошибки в скольугодно сложную систему протоколирования и управление ресурсами.
Я думал и о контекстной обработке ошибок и восстановлении вычислительного процесса, но понял, что конструкции try catch здесь более чем достаточно, и никакие специфические макроопределения по этому поводу в модуле fcn не созданы. Надо только не мешать две концепции. Например вместо:
try{ fcn_protect(myfun1(), "Error message 1!"); }
catch(...)
{
// do something
}
fcn_protect(myfun2(), "Error message 2!");
Писать нечто вроде:
try{ throw myfun1(); }
catch(FStatus status)
{
if(status == FOK())
{
// do something
}
else
{
// do something else
}
}
catch(...)
{
// do something
}
fcn_protect(myfun2(), "Error message 2!");
Иначе если последовательно произойдет ошибка в myfun1 и будет перехвачена в catch а потом еще произойдет ошибка в myfun2, то в отчет поступит информация о первой ошибке, потому что ее контекст был сохранен макроконструкциями и действует до окончания работы функции. Просто не надо мешать средства модуля fcn и обычный анализ ошибок.
По поводу исключений скажу что хотя эт теоретически оч мощное средство, я стараюсь его избегать :(. В моем дебаггере исключения вызывают останов выполнения и если их много программу оч сложно отлаживать. Вообще пора уже было начать объявлять все функции как nothrow(), но я этого не делаю. По сути все проверки выполняются в виде анализа FStatus и его наследников. FStatus можно возвращать как результат функции, он хранит в себе информацию об ошибке, и хотя для всяких dynamic_cast это будет FStatus, а не его наследник, но операции сравнения работают корректно. Анализ исключительных ситуаций я применяю, но только когда это действительно необходимо, что бывает редко, т.к. я использую минимум готовых функций.
Механизм защелок я никада не использовал. Он мне понравился. И притом похоже на современных компиляторах корректно вызываются деструкторы даже при выходе из блоков с помощью goto, как бы это уже не было неактуально :)