Lately I've found the more I avoid the exception approach, the more I dislike the exception approach, the more I start to think that if recovery is probably, exceptions aren't the correct way to go.
Error condition resolving seems to have several approaches:
* Return object and throw exception on error. Immutable, but causes exceptions to be handled in an "expected" code path. Dislike.
* Return error code and emit value as an out parameter. Requires mutability for out parameters. Dislike.
* Return nullable/falsable data and use some other error reporting. Difficult in multithreaded scenarios as whilst values are immutable the errors mutable, and requires all returns to be checked despite that need being non-obvious. Dislike.
* Returning an explicit type that contains error details when error occurs, and the value when success occurs. Still requires the check, but that need is more explicit. So far, the best approach I've found for when failure is an expected code path.
So loading a texture could look more like:
sf::Result<sf::Texture> texture = sf::Texture::loadFromFile("file.png");
if (!texture)
std::cerr << texture.err() << std::endl;
sf::Texture actualTexture = *texture;
But exceptions are a common way of handling this, and I've even argued for them before. It comes down to the implied preconditions of the function. If the precondition doesn't specify that the file exists, then the response should reflect that and the optional pattern is the correct choice in my mind. An implied pre-condition to loadFromFile is that the file exists, so an exception is the correct response to trying to load when the file does not exist.