True. So we're back in the boat of having to clear errno
manually. In general, do you clear and check errno for each
POSIX function, or do you prefer to avoid clearing errno when
possible?
I wouldn't say that I consciously avoid clearing errno, but I
don't bother clearing it if the function provides another means
of determining that there was an error. (I don't clear it
before open or read, for example.)
And just a nit: strtol and errno aren't just Posix---they're
part of the C standard, and by reference the C++ standard. So
the same rules apply under Windows.
I think Jean-Marc and you have changed my mind, but I still
would prefer to check for the tradiditional -1 (or null) when
possible.
Certainly. The problem is that *you* don't get the choice. How
you determine whether there was an error, and how you determine
what the error was if there was one, is specified by the
function, not by you. I'd never design a function to use errno,
and generally, the policy of Posix is also not to use it in new
functions, but rather to return a status code, and use out
arguments for other "return values" (see anything in
<pthread.h>, for example. I (and everyone I know) consider
errno a historical wart; something we have to live with, like it
or not.
Then the caller can use a try/catch block. That isn't much
more syntax than an if-statement,
Oh yes it is, since it implies creating a scope for the call
(and not just for the error handling). Which in turn may mean
either moving the error handling down further in the function,
or declaring the variable before initializing it.
it allows the compiler to favor the case in which an error
does not happen,
It can do this in any case.
and it keeps the error-handling code separate from the main
logic.
Which isn't necessarily an advantage, for errors which have to
be handled immediately.
I don't see any reason at all to prefer cursing a particular
return value; that seems more like dark magic to me.
Furthermore, if the caller forgets to check the return code
for its error value, a silent bug is likely to ensue, whereas
an exception will make itself heard unless explicitly
squashed.
Fallible aborts if you access the return value when the status
is invalide. Fallible supports some syntactic sugar as well,
e.g.: getSomething().elseDefaultTo( defaultValue ). And it's no
more dark magic than exceptions---less, really.
To me, strtol also seems to be a very low-level function, and
doesn't seem likely to know what to do on failure, anyway. At
the time strtol was written, of course, the situation probably
was different.
Even today, maybe. But I think the most frequent use would be
in the implementation of the operator>> in istream, or other low
level code of this sort. But at this point, we're so low that
you'll almost want to handle the error immediately, in order to
map it to the class specific error reporting mechanism.
To me, that means: "This isn't really an error. It's
something I expect to happen in the course of normal
operation,
That's also true. Although that's not really my argument. But
I don't think you can consider any format error in input
"exceptional". Just the opposite, you're almost certain to see
it from time to time.
and I want to be able to check for it at my leisure."
That's not Fallible; that's the idiom used by std::istream (and
IEEE floating point). It's also useful---in the case of output
(std:
stream) and floating point, it's probably the preferred
idiom. (Typically, I'll output an entire file, and only check
the status and generate an error return after close.) In the
case of input, I almost always want to know about the error
immediately, so I can output an error message with significant
context.
I don't see anything inherently wrong with that, but it really
changes the discussion. (I'd still prefer an exception for
strtol, but I could see the Fallible PoV.)
In the case of strtol, there's another, clinching argument
against exceptions: the function has to be usable from C
.
And since we can't break existing code, it has to use errno:-(.
If we're talking about a new function, with similar use, I think
it would depend very much on the requirements I was faced with.
As I think I already said, if the function were designed for
higher level used, I'd probably do something like istream.
Yes, at least insofar as it lets the client dictate what's an
error. To me, EOF isn't (necessarily) an error, and I don't
want an exception when I hit it; by contrast, failure to read
an integer where one is expected does constitute such an
error.
That's where we disagree. An error in input format is really to
be expected, at least in most cases. What I generally don't
expect (and would consider exceptional, and report by an
exception) might be a hardware read error (except, perhaps, in
very, very low level code, e.g. an implementation of a level 2
or a level 3 protocol, like LAP-D or IP).