This is one of those awkward questions where it is hard to think of anything sensible to put on the title. Maybe I can retitle retrospectively...
I'm dealing with the following code:
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;
}
}
As can be seen, the same pattern occurs in each of the three cases.
Also in the third case, the function signature has an extra parameter, although experimentation suggests I can add a dummy parameter to the first two cases if need be.
I can't see any possible way of abstracting the mechanism short of using #define-s.
Is there anything to be done?
The only thing that comes to mind is something like this:
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();
}
}
Then, one example of how you'd use that:
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;
});
}
And the other instances would convert similarly.
This'll still lead to a lot of template bloat, of course; but at least the source code will be tight, and compact.