2014-11-15 1 views
0

Это один из тех неудобных вопросов, когда трудно придумать что-нибудь разумное, чтобы надеть заголовок. Может быть, я могу переименуйте ретроспективно ...Удалить дублирование в C++ 11 try catch pattern

Я имею дело со следующим кодом:

static FinalClass* final_class(PyObject* o) {/*...*/} 

    template< F0 f > 
    static PyObject* handler(PyObject* o, PyObject*) 
    { 
     try 
     { 
      Object result{ (final_class(o) ->* f)() }; 
      return new_reference_to(result.ptr()); 
     } 
     catch(Exception &) 
     { 
      DBG_LINE("! ! ! Exception Python calling new-style-class handler ! ! !"); 
      return 0; 
     } 
    } 

    template< F1 f > 
    static PyObject* handler(PyObject* o, PyObject* _a) 
    { 
     try 
     { 
      Object result{ (final_class(o) ->* f)(Tuple{_a}) }; 
      return new_reference_to(result.ptr()); 
     } 
     catch(Exception &) 
     { 
      DBG_LINE("! ! ! Exception Python calling new-style-class handler ! ! !"); 
      return 0; 
     } 
    } 

    template< F2 f > 
    static PyObject* handler(PyObject* o, PyObject* _a, PyObject* _k) 
    { 
     try 
     { 
      Object result{ (final_class(o) ->* f)(Tuple{_a}, Dict{_k}) }; 
      return new_reference_to(result.ptr()); 
     } 
     catch(Exception &) 
     { 
      DBG_LINE("! ! ! Exception Python calling new-style-class handler ! ! !"); 
      return 0; 
     } 
    } 

Как видно, такая же картина происходит в каждом из трех случаев.

Также в третьем случае сигнатура функции имеет дополнительный параметр, хотя эксперименты позволяют мне добавить фиктивный параметр в первые два случая, если это необходимо.

Я не вижу никакого способа абстрагирования механизма, не используя # define-s.

Есть ли что-нибудь, что нужно сделать?

+0

Возможный дубликат [Возможно ли писать/переносить компоненты обработки исключений (try, catch) в разных классах?] (Http://stackoverflow.com/questions/25579323/is-it-possibe-to -write-wrap-the-exception-handling-componentetstry-catch-in-diffe) –

+0

Не забывайте о макросах. – Peter

ответ

1

Единственное, что приходит на ум, это что-то вроде этого:

template<typename functor_type, typename default_value_functor> 
auto execute_and_catch(functor_type &&functor, 
         default_value_functor &&default_value) 
    -> decltype(functor()) 
{ 
    try 
    { 
     return functor(); 
    } 
    catch(Exception &) 
    { 
      DBG_LINE("! ! ! Exception Python calling new-style-class handler ! ! !"); 
      return default_value(); 
    } 
} 

Тогда один пример того, как вы будете использовать, что:

template< F0 f > 
static PyObject* handler(PyObject* o, PyObject*) 
{ 
    execute_and_catch([&] 
     { 
      Object result{ (final_class(o) ->* f)() }; 
      return new_reference_to(result.ptr()); 
     }, 
     [] 
     { 
      return 0; 
     }); 
} 

И другие примеры преобразовал бы так же.

Это все равно приведет к много раздуванию шаблонов, конечно; но, по крайней мере, исходный код будет плотным и компактным.

1

Может быть, вы можете сделать что-то с variadic templates, при условии, что Tuple имеет конструктор, который может взять PyObject* в качестве входных данных, например:

template< typename F, typename... Params > 
static PyObject* handler(F f, PyObject* o, Params... p) 
{ 
    try 
    { 
     Object result{ (final_class(o) ->* f)(p...) }; 
     return new_reference_to(result.ptr()); 
    } 
    catch(Exception &) 
    { 
     DBG_LINE("! ! ! Exception Python calling new-style-class handler ! ! !"); 
     return 0; 
    } 
} 

PyObject* h = handler(&someF0method, o); 

PyObject* h = handler(&someF1method, o, a); 

PyObject* h = handler(&someF2method, o, a, b); 
+0

'p' никогда не расширяется ... – ildjarn

+0

Я изменил' p' на 'p ...'. –