Здравствуйте, 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))