Reputation: 1491
I would like to create a class which takes std::function and allow to handle specified exceptions but I'm not sure if it is possible.
Here is a pseudo draft:
//exception types
template<class... Args>
class CustomExceptionHandler
{
public:
CustomExceptionHandler(std::function<void()> clb): clb_(std::move(clb)){}
void ExecuteCallback()
{
try
{
clb_();
}
/*catch specified exception types*/
}
private:
std::function<void()> clb_;
};
//usage
CustomExceptionHandler<std::out_of_range, std::overflow_error> handler(clb);
handler.ExecuteCallback();
I don't know how to use a variadic template to grab exception types and use it later. Is it possible?
I guess that tuple may be helpful.
Upvotes: 10
Views: 517
Reputation: 7202
It's possible! I've made a solution (which you can run here) that expands the parameter pack of exception types into a series of recursive function calls, where each function attempts to catch one type of exception. The innermost recursive call then invokes the callback.
namespace detail {
template<typename First>
void catcher(std::function<void()>& clb){
try {
clb(); // invoke the callback directly
} catch (const First& e){
// TODO: handle error as needed
std::cout << "Caught an exception with type \"" << typeid(e).name();
std::cout << "\" and message \"" << e.what() << "\"\n";
}
}
template<typename First, typename Second, typename... Rest>
void catcher(std::function<void()>& clb){
try {
catcher<Second, Rest...>(clb); // invoke the callback inside of other handlers
} catch (const First& e){
// TODO: handle error as needed
std::cout << "Caught an exception with type \"" << typeid(e).name();
std::cout << "\" and message \"" << e.what() << "\"\n";
}
}
}
template<class... Args>
class CustomExceptionHandler
{
public:
CustomExceptionHandler(std::function<void()> clb): clb_(std::move(clb)){}
void ExecuteCallback()
{
detail::catcher<Args...>(clb_);
}
private:
std::function<void()> clb_;
};
int main(){
std::function<void()> clb = [](){
std::cout << "I'm gonna barf!\n";
throw std::out_of_range("Yuck");
//throw std::overflow_error("Ewww");
};
CustomExceptionHandler<std::out_of_range, std::overflow_error> handler(clb);
handler.ExecuteCallback();
return 0;
}
Output:
I'm gonna barf!
Caught an exception with type "St12out_of_range" and message "Yuck"
Upvotes: 10
Reputation: 37607
template<typename E0, typename ... En>
class ExceptionCatcher
{
public:
template<typename F>
void doit(F&& f)
{
try
{
ExceptionCatcher<En...> catcher;
catcher.doit(std::forward<F>(f));
}
catch(const E0 &)
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
}
};
template<typename E0>
class ExceptionCatcher<E0>
{
public:
template<typename F>
void doit(F&& f)
{
try
{
f();
}
catch(const E0 &)
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
}
};
https://wandbox.org/permlink/dAUQtb9RWvMZT4b6
Upvotes: 2