We're not going to allow that to propagate.
O_o
Why?
You could try to refactor this into a function, and you would get:
You could split the translation code into a function, or you could combine both mechanisms into a private interface.
Code:
OurMyIoOp(); // We allow a private implementation
OurMyIoOp(); // to transform the exception on
OurMyIoOp(); // our behalf instead of duplicating code.
The difference is now that the error handling has been moved to the catch handler instead of having to write verbose code for every line to check for errors.
This comment is wrong.
You aren't handling the error; you are only translating the error.
The difference is that the translation code has been moved to a local catch handler so that the check doesn't need to be duplicated, wrapped, or similar.
Scenario 3. The library throws returns an error.
o_O
Which?
We can use a macro or function with a lambda to deal with that, which makes it a little bit better, but still verbose:
You could split the swallowing code into a function, or you could combine both mechanisms into a private interface.
Code:
OurMyIoOp(); // We internally swallow the exception.
Sometimes we can use helper functions such as CanOpenFile which [...] attempts to open the file.
We are talking about a situation where we have one or more known alternative to accomplish a similar goal in the case of failure; we are talking about a situation where the code can not continue when one of the alternative succeeds. You can almost always use create a `OpenOrCreateFile' function. The combined interface internally handles the attempts to allow each alternative to succeed.
Code:
auto_ptr<MyFile> s(CreateOrOpenFile(/* ... */));
We may then handle errors from interfaces that have no alternative using some other discussed method.
Code:
try
{
auto_ptr<MyFile> s(CreateOrOpenFile(/* ... */));
// We may wrap the translation code if we get a return value.
OurReadFile(s, /* ... */); // if(ReadFile(s, /* ... */) != OK) // throw Whatever(/* ... */);
OurReadFile(s, /* ... */); // if(ReadFile(s, /* ... */) != OK) // throw Whatever(/* ... */);
OurReadFile(s, /* ... */); // if(ReadFile(s, /* ... */) != OK) // throw Whatever(/* ... */);
}
catch(/* ... */)
{
throw Something(/* ... */); // We may translate an exception.
}
The diference here is that we potentially have many try/catch statements and not just a single global one that covers all exceptions.
We our C++ programmers. We do not accept a repeating "potentially have many try/catch statements and not just a single global one that covers all exceptions" problem throughout our client code. We translate the errors we need behind a private interface so that we do not have to repeat ourselves.
Code:
auto_ptr<MyFile> sIn(CreateOrOpenFile(/* ... */)); // Try the alternative options allowing other
auto_ptr<MyFile> sOut(CreateOrOpenFile(/* ... */)); // failures to propagate or translate the errors we need.
try
{
OurReadFile(/* ... */);
OurWriteFile(/* ... */);
}
catch(/* Read */)
{
// Whatever
}
catch(/* Write */)
{
// Whatever
}
catch(/* ... */)
{
// Whatever
}
[Edit]
By enabling the library to conditionally throw an exception.
It doesn't change the fact that we have to handle the error. It changes where we handle the error by making the code less verbose.
Indeed. Everything I described about handling the different approaches to reporting an error may be handled internally so that the relevant boilerplate propagation/translation code isn't necessary.
[/Edit]
Soma