Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to catch an exception of lambda type?

While it is good practice to throw only exceptions of types derived from std::exception class, C++ makes it possible to throw anything. All below examples are valid C++:

throw "foo";  // throws an instance of const char* throw 5;      // throws an instance of int  struct {} anon; throw anon;   // throws an instance of not-named structure  throw []{};   // throws a lambda! 

The last example is interesting, as it potentially allows passing some code to execute at catch site without having to define a separate class or function.

But is it at all possible to catch a lambda (or a closure)? catch ([]{} e) does not work.

like image 412
Krzysiek Karbowiak Avatar asked Dec 05 '18 09:12

Krzysiek Karbowiak


People also ask

How do you catch exceptions in lambda?

The most straightforward way would be to use a try-catch block, wrap the checked exception into an unchecked exception and rethrow it: List<Integer> integers = Arrays. asList(3, 9, 7, 0, 10, 20); integers. forEach(i -> { try { writeToFile(i); } catch (IOException e) { throw new RuntimeException(e); } });

Can you throw exception from lambda?

A lambda expression cannot throw any checked exception until its corresponding functional interface declares a throws clause. An exception thrown by any lambda expression can be of the same type or sub-type of the exception declared in the throws clause of its functional interface.

How do you handle exception thrown by lambda expression?

A lambda expression body can't throw any exceptions that haven't specified in a functional interface. If the lambda expression can throw an exception then the "throws" clause of a functional interface must declare the same exception or one of its subtype.


1 Answers

Exception handlers are matched based on type, and the implicit conversions done to match an exception object to a handler are more limited than in other contexts.

Each lambda expression introduces a closure type that is unique to the surrounding scope. So your naive attempt cannot work, for []{} has an entirely different type in the throw expression and the handler!

But you are correct. C++ allows you to throw any object. So if you explicitly convert the lambda before-hand to a type that matches an exception handler, it will allow you to call that arbitrary callable. For instance:

try {     throw std::function<void()>{ []{} }; // Note the explicit conversion } catch(std::function<void()> const& f) {     f(); } 

This may have interesting utility, but I'd caution against throwing things not derived from std::exception. A better option would probably be to create a type that derives from std::exception and can hold a callable.

like image 178
StoryTeller - Unslander Monica Avatar answered Sep 22 '22 10:09

StoryTeller - Unslander Monica