Re[3]: Execution guard
От: Кодт Россия  
Дата: 11.11.09 23:06
Оценка:
Здравствуйте, denisko, Вы писали:

D>Да просто все, у нас есть товарищь, который ОООЧЕНЬ любит писать так

D>
D> bool func(arg1,arg2....argN)
D>{
D> if(isValid(arg1) && isValid(arg2) && ..........)
D> {
D>   if(andNobodyWantsToThrowSomeShit(member1,memer2,member3))
D>   {
D>      if(bullShitCondition1(..))
D>      {
D>         if(bullShitCondition2(...))
D>         {
D>            if(!bullShitConditionN(...))
D>            {
D>               throw wowIfuckedYourGuidelinesException;
D>            }
D>            else
D>            {
D>               return arg1 != arg2
D>            }
D>         }
D>      }
D>   }
D>   return false;
D> }
D>

D>и гордится этим.

Методы социального рефакторинга не пробовали?
Или, например,
struct trap
{
  // любой правоассоциативный оператор с низким приоритетом
  template<class Exception> trap& operator <<= (Exception const& e)
  {
    handle_the_exception(e); // пишет в лог, взводит флаг, утилизирует объект (если надо)
    return *this;
  }

  // для возвращения
  template<class Return> operator Return() const { return Return(); }
};

#ifdef пожалеем_раздолбая
#define throw  trap() <<= /*исключение*/
#else
#define throw !!! по голове себе постучи !!!
#endif


D>1) По ряду причин, мы не используем исключения (слишком много наследного кода, причем шаблонного, который не поддерживает исключения).



D>Хочется иметь что-нибудь типа такой структуры

D>где SAFE_CALL -- ловит все разумные исключения товарища, пишет в лог и выставляет код ошибки. Как писать понятно, но писать нудно -- надо кучу операторов скобочка для каждого аргумента, да и наверняка это где то реализовано, вот такую реализацию я и ищу.

Чтобы самому не заниматься с многоарными функциями, а сосредоточиться только на сути — задействуй boost::bind

Что-нибудь в таком роде:
template<class F>
typename boost::result_type<F>::type
safecall(F f)
{
  try
  {
    return f();
  }
  catch(...)
  {
    rethrow_handle_and_absorb();
    return default_value();
  }
}

// обработчик исключений, вынесенный за пределы вызова проблемного кода
void rethrow_handle_and_absorb
{
  try { throw; } // переизлучаем... но мы должны быть уверены, что вызвали эту функцию из catch(...)
  catch(aaa) { .... }
  catch(bbb) { .... }
  catch(ccc) { .... }
  catch(...) { .... }
}

// универсальный результат - приводится ко всем типам на свете
struct default_value
{
  template<class T> operator T() const { return T(); }
};

// вызываем
.... safecall(boost::bind(foo,1,2,3,4,5)) .....

А если хочешь биндить этот safecall, то
// карринг параметров шаблона: возвращаемый тип R отдельно,
template<class R> struct safecaller
{
  typedef R result_type;
  // а принимаемый F - отдельно
  template<class F> R operator()(F f) const { return safecall(f); }
};

// используем...
bar( .....
     bind(
       safecaller<bool>(), // тип объекта и тип result_type для bind нужны сразу (он их замучается выводить)
       protect( // изолируем внутренний бинд от внешнего
         bind(foo,1,2,3,4,5)
       ) // то есть, внутрь safecall<bool>()(_) приедет не результат вызова foo(1,2,3,4,5), а сам бинд
     )
     .....
    );

void bar(...., F f, .....) // F изоморфен bool(), т.е., например, function<void()> или параметр шаблона
{ ..... f(); ..... } // здесь f() тождественно предыдущей форме safecall(bind(foo,1,2,3,4,5))
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.