Is it possible to catch an exception of lambda type?

  • A+
Category:Languages

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.

 


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.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: