Re[3]: Оформление обработки ошибок в plain C
От: _nn_  
Дата: 19.06.04 14:23
Оценка:
Здравствуйте, barmafon, Вы писали:

TC>>еще один вариант — "липовый" do {}while(0);

TC>>плюсы :
TC>> + в любом месте можно выйти из него простым break не заботясь о вызове деструкторов
TC>> + все деструкторы вызываются в одном месте
TC>> + несмотря на похожесть на вариант с goto тут нет меток
TC>> + внутри do {} while() можно завести какой локальный объект внутри тела блока.
TC>> минусы :
TC>> — кому то может показаться что do {} while() используется не по делу)
TC>> — код все таки уползает вправо хотя и медленно.
TC>> — проверки на NULL режут глаз

B>для устранения минуса №3 можно воспользоваться следующей техникой:

B>
B>int f()
B>{
B>  int stage, failed;
B>  void *obj1;
B>  void *obj2;
B>  for( stage = 0;; ) {
B>    if( !(failed=construct_obj1(&obj1)) )
B>      break;
B>    ++stage;
B>    if( !(failed=construct_obj2(&obj2)) )
B>      break;
B>    ++stage;
B>    if( !(failed=do_something(obj1,obj2)) )
B>      break;
B>    ++stage;
B>    break;
B>  }

B>  switch( stage ) {
B>  case 3: break;
B>  case 2: destruct_obj2(obj1);
B>  case 1: destruct_obj1(obj1);
B>  }

B>  return failed;
B>}
B>


B>плюсы:

B>+ красиво
B>+ мы не обязаны инициализировать указатели на создаваемые объекты
B>минусы:
B>- нужна специальная переменная stage
B>- отслеживание значений переменной stage в каждой точке инициализации

Может воспользоватся макросами :
int f()
{
    void *obj1;
    void *obj2;
    BEGIN_ERROR()
        BEGIN_INIT()
            ERROR_INIT1(construct_obj1,&obj1)
            ERROR_INIT1(construct_obj2,&obj2)
            ERROR_INIT2(do_something,&obj1,&obj2)
        END_INIT()
        BEGIN_TEST()
            ERROR_TEST(3)
            ERROR_TEST1(2,destruct_obj2,&obj2)
            ERROR_TEST1(1,destruct_obj1,&obj1)
        END_TEST()
    END_ERROR()
}

Сами макросы :
#define STAGE_VAR \
    stage_unique_name__

#define FAILED VAR \
    failed_unique_name__

#define BEGIN_ERROR() \
    { \
        int STAGE_VAR=0; \
        int FAILED_VAR=0;

#define END_ERROR() \
        return FAILED_VAR; \
    }

#define BEGIN_INIT() \
        while(1) \
        {

#define END_INIT() \
            break; \
        }

#define ERROR_INIT0(f) \
    if(!(FAILED_VAR=f())) \
        break; \
    ++STAGE_VAR;

#define ERROR_INIT1(f,p1) \
    if(!(FAILED_VAR=f(p1))) \
        break; \
    ++STAGE_VAR;

#define ERROR_INIT2(f,p1,p2) \
    if(!(FAILED_VAR=f(p1,p2))) \
        break; \
    ++STAGE_VAR;

#define BEGIN_TEST() \
    switch(STAGE_VAR) \
    {

#define END_TEST() \
    }

#define ERROR_TEST(n) \
    case n: break;

#define ERROR_TEST0(n,f) \
    case n: f();

#define ERROR_TEST1(n,f,p1) \
    case n: f(p1);

#define ERROR_TEST2(n,f,p1,p2) \
    case n: f(p1,p2);
http://rsdn.nemerleweb.com
http://nemerleweb.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.