← Back to context

Comment by identity0

5 years ago

The obvious solution (in C++) is not to use exceptions at all, but make your own `error` and `expected<T>` class, and just add [[nodiscard]] to them. All the benefits of Go-style errors, you’ll never forget to check the error, and there is very little runtime overhead. If you pass the error as an out parameter then there is zero runtime overhead on success.

Speaking of C++ exceptions: Andrei Alexandruesco has investigated the performance impact of replacing exceptions with error codes. Dave Cheney made a summary of Andreis points in https://dave.cheney.net/2012/12/11/andrei-alexandrescu-on-ex...

* The exceptional path is slow (00:10:23). Facebook was using exceptions to signal parsing errors, which turned out to be too slow when dealing with loosely formatted input. Facebook found that using exceptions in this way increased the cost of parsing a file by 50x (00:10:42). No real surprise here, this is also a common pattern in the Java world and clearly the wrong way to do it. Exceptions are for the exceptional. * Exceptions require immediate and exclusive attention (00:11:28). To me, this is a killer argument for errors over exceptions. With exceptions, you can be in your normal control flow, or the exceptional control flow, not both. You have to deal with the exception at the point it occurs, even if that exception is truly exceptional. You cannot easily stash the first exception and do some cleanup if that may itself throw an exception.

There is still runtime overhead in that you have to check whether you succeeded. The best possible scenario is if the error source knows exactly what code to jump to in the error case, and the calling code can assume that no error occurred if it is running. So in that sense it can be done better. But I'm not sure how material this difference is in light of correct branch prediction in the success path.