[0]: http://blog.man7.org/2012/10/how-much-do-builtinexpect-likel...
My experience has been that error paths have a way of getting things into inconsistent states, and then you're in trouble regardless.
Checking return codes is annoying but if you're wanting to write robust software, your code needs to be in some way aware of every possible error path.
To be fair, there are compiler flags to check this. And if not, there are static analysis tools that do the same.
There's also the [[nodiscard]] attribute of c++17.
Option/Result are really well designed and let you express all sorts of wonderful flow. Being able to .and_then(), .or_else() or the combination of them and many others is just sublime. The doc page goes into quite a bit of detail: https://doc.rust-lang.org/book/error-handling.html
It takes some time getting used to, but it also creates the habbit of checking error codes on every function you call. It also makes handling errors something you do as soon as possible (and in the most recoverable way).