Boost logo

Boost :

Subject: Re: [boost] Noexcept
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2017-06-13 21:01:26


On Tue, Jun 13, 2017 at 12:25 AM, Andrzej Krzemienski via Boost <
boost_at_[hidden]> wrote:

> > let's not forget that if f() fails, y is invalid and g()
> > should reject it (think of it as e.g. fread getting a 0 for its FILE *
> > parameter).
>
> I absolutely agree that it is wrong to pass an invalid `y` to `g()`, I
> think we are just disagreeing on who is responsible for preventing this
> from happening.
>

I think that I don't disagree at all, but I am pointing out that 1) no
matter what, g() *should* assert on its preconditions anyway, and 2) if
there is a danger for g() to silently not fail when given bad data, then
the choice of return type for f() is poor. For example, usually I'm not
terribly worried of the following bug escaping undetected:

shared_ptr<foo> f();
void g( foo & );
....
g(*f()); //bug, no error check

That's because dereferencing an empty shared_ptr fails dramatically, in
fact (if exceptions are disabled) just as dramatically as if I had:

result<shared_ptr<foo> > f();
void g( foo & );
....
g(*f().value() ); //.value checks for errors

You say that in case of Noexcept, there is an assertion, but I fail to see
> where you could put this assertion, so that a call to `g()` is prevented.
> Maybe you could elaborate?
>

Misunderstanding. The call to g() is not prevented, what's prevented is the
attempt of g() to call throw_ if the error from f() wasn't handled.

But again, I agree with all of your concerns, it's just that they're
(mostly, not 100%) orthogonal to what Noexcept lets you do. If you feel
that you want to put a FILE * into some result<T>, more power to you (do
note that since in Noexcept that type doesn't have to transport errors, it
can be implemented in 2 lines in terms of optional<T>).

> > Perhaps your point is that ideally f() shouldn't return int but a
> different
> > type with special semantics. Okay.
> >
> > OTOH let's say you're returning a file descriptor. I'd think that
> > optional<int> is an overkill in this case, in fact you're probably
> > obfuscating the fact that the int is a FD -- what does it mean if you get
> > -1 FD in an optional<int> (or for that matter in an outcome<int>)? It's
> > redundant, and after all it's a safe assumption that you won't get silent
> > failures from functions if you pass -1 for the FD.
>
> A valid concern. A solution to that has been provided by Vicente: just use
> type `uncertain<T>`, which is just a `T` inside, but because it is a
> different type, you cannot silently use it in place of `T`. But this would
> compromise your other goal: that some functions want to remain
> exception-neutral.
>

How does it compromise it? This uncertain<T> must still have an invalid
state, a value that is returned when there is an error. If that value is
simply uncertain<T>() (which, obviously, it is), you can just return
throw_(my_error()) from a neutral function that returns uncertain<T>.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk