What you ask is possible, but I do not think it is very useful. First, give the opportunity to implement a mechanism for accepting the called object and the arguments associated with it, which we will call in the exception_wrapper destructor.
template<typename Func, typename... Args> struct exception_wrapper { exception_wrapper(Func f, Args... args) : f_(std::move(f)) , args_(std::make_tuple(std::move(args)...)) {} ~exception_wrapper() { try { invoke(); } catch(std::exception const& e) { std::cerr << "Caught exception: " << e.what() << std::endl; } catch(...) { std::cerr << "Caught unknown exception" << std::endl; } } template<std::size_t... I> void apply(std::index_sequence<I...>) { f_(std::get<I>(args_)...); } void invoke() { apply(std::index_sequence_for<Args...>()); } Func f_; std::tuple<Args...> args_; }; template<typename Func, typename... Args> auto make_exception_wrapper(Func&& f, Args&&... args) { return exception_wrapper<Func, Args...>( std::forward<Func>(f), std::forward<Args>(args)...); }
This uses C ++ 14 std::integer_sequence ; if this is not available for your implementation, there are several answers to SO that show how to implement it yourself ( this one ).
To use it, create an exception_wrapper object, and your function will be called when the destructor runs.
make_exception_wrapper(function);
Live demo
Now I do not think this is useful, because in the general case you should catch only exceptions if your code is able to handle them and continue to work normally. Otherwise, they will propagate to the upper level, where you may want to install a handler so that it can gracefully exit the program.
Given this, it is unlikely that there will be a general approach to handling all exceptions thrown by your code, which greatly reduces the usefulness of exception_wrapper , as implemented. You can modify it to accept another argument being called, an exception handler that will be passed the std::exception object that has been caught, which makes the class more universal.
In addition, calling a function in the destructor means that you cannot pass the return value, if any, back to the caller. This can be fixed by calling the function inside exception_wrapper::operator() instead, but then it adds a wrinkle to what should be returned if the exception is really thrown and you suppressed it.
Finally, do not write code that yields types that are not derived from std::exception . This makes your code unified, and if you want to handle an exception, you will need to lure the code with several catch statements, as was the case in your example.