Здравствуйте, ononim, Вы писали:
O>>>И для каждого случая рисовать свою структуру? Тогда уж проще по старинке...
_>>Зачем. Как обрабатывать отказы должен задавать вызывающий. И вообще включи воображение. Вариантов тьма.
O>Вариантов тьма. А вот варинтов таких, чтобы нуб придя на проект в течении секунд 20 врубился что делает код сейчас ровно один:
O>O>try
O>{
O>work();
O>}catch
O>{
O>repair();
O>work();
O>}
O>
O>Ваши примеры к таким не относятся. Кроме того последний вариант требует "заточки" под себя кода, который он обслуживает, что опять же ухудшает понимабельность и рефакторабельность кода.
Нет проблем. Только кому это надо?
struct ECritical {};
struct EIgnorable {};
struct Try {
int stage,limit;
enum { Recover=0,Body=1,Success=2,Leave=3 };
Try(int count) { stage=1;limit=count-1; }
operator int() { return stage!=3; }
void step() { if (stage==0) stage=1; stage++; }
void handle() {
if (stage<=1) {
check_exception();
if (limit>0) { limit--; stage=-1; }
else throw;
} else {
throw;
}
}
void check_exception() {
try { throw; }
catch(ECritical) { throw; }
catch(EIgnorable) { }
catch(...) { /*unexprected*/ throw; }
}
};
#define TRY_LIMIT(n) try{for(Try t(n);t;t.step()) { try { switch(t.stage) {
#define RECOVER case 0:
#define BODY case 1:
#define SUCCESS break; case 2:
#define FAIL }} catch(...) { t.handle(); }}} catch(...) {
#define END_REPEAT }
...
int ok=0;
TRY_LIMIT(3)
RECOVER { gc(); }
BODY { some_work(); }
SUCCESS { ok=1; }
FAIL { ok=0; /*throw;*/ }
END_REPEAT