(libc++) get_unexpected expected to return non-NULL

The test:

\test\std\depr\exception.unexpected\set.unexpected\get_unexpected.pass.cpp

expects the initial unexpected handler to be non-NULL:

int main()
{

std::unexpected_handler old = std::get_unexpected();
// verify there is a previous unexpected handler
assert(old);

Is that really a requirement?

The test:

\test\std\depr\exception.unexpected\set.unexpected\get_unexpected.pass.cpp

expects the initial unexpected handler to be non-NULL:

int main()
{

    std::unexpected_handler old = std::get_unexpected();
    // verify there is a previous unexpected handler
    assert(old);

Is that really a requirement?

I believe so, yes. [unexpected.handler]p3 says: "The implementation’s
default unexpected_handler calls std::terminate()." which suggests
that there be an initial default unexpected_handler that is nonnull.

~Aaron

I personally think the standard is poorly defined here. It allows for the case that get_unexpected can return null. It also allows it to be legal to call set_unexpected with null, but doesn’t specify whether that means set the default handler.

libc++ allows null but unexpected() will crash if called in when the unexpected handler is null. Also it doesn’t have any code to set the default handler out of the box (unless I’m missing something). Any idea why this is the case? The reason I brought this up is that tests were asserting and crashing for me (with MSVC) because in my build I haven’t (yet) done anything to set a default.

I personally think the robust solution for behaviour is to return null from the outset and have std::unexpected just call terminate if the current handler is null. That way there’s no nasty behaviour. However, if the choice for libc++ is to have a non-null handler then is there any reason not to add code to set that automatically (to std::terminate) and possibly add code to do something sane when null is passed in?

Anyway, I won’t stress too much about this as it’s deprecated in c++11 and not going to end my world. Just curious as to why things are the way they are.

I personally think the standard is poorly defined here. It allows for the
case that get_unexpected can return null. It also allows it to be legal to
call set_unexpected with null, but doesn't specify whether that means set
the default handler.

libc++ allows null but unexpected() will crash if called in when the
unexpected handler is null.

Which it is allowed to do.

Also it doesn't have any code to set the
default handler out of the box (unless I'm missing something). Any idea why
this is the case? The reason I brought this up is that tests were asserting
and crashing for me (with MSVC) because in my build I haven't (yet) done
anything to set a default.

I believe libc++ relies on the ABI libraries to provide these default
implementations, but I'm not 100% certain as I'm not a libc++ expert.

I personally think the robust solution for behaviour is to return null from
the outset and have std::unexpected just call terminate if the current
handler is null. That way there's no nasty behaviour. However, if the
choice for libc++ is to have a non-null handler then is there any reason not
to add code to set that automatically (to std::terminate) and possibly add
code to do something sane when null is passed in?

Others may have a better answer than me, but I am not certain it's
worth the added complexity for deprecated functionality.

~Aaron

> I personally think the standard is poorly defined here. It allows for
the
> case that get_unexpected can return null. It also allows it to be legal
to
> call set_unexpected with null, but doesn't specify whether that means set
> the default handler.
>
> libc++ allows null but unexpected() will crash if called in when the
> unexpected handler is null.

Which it is allowed to do.

> Also it doesn't have any code to set the
> default handler out of the box (unless I'm missing something). Any idea
why
> this is the case? The reason I brought this up is that tests were
asserting
> and crashing for me (with MSVC) because in my build I haven't (yet) done
> anything to set a default.

I believe libc++ relies on the ABI libraries to provide these default
implementations, but I'm not 100% certain as I'm not a libc++ expert.

Yes, I think you're right and this probably addresses the crux of my

issues. I've been using libc++abi on GNU platforms but that's not viable
with MSVC. Spent too long with my head in VC and missed this piece of the
puzzle.

> I personally think the robust solution for behaviour is to return null
from
> the outset and have std::unexpected just call terminate if the current
> handler is null. That way there's no nasty behaviour. However, if the
> choice for libc++ is to have a non-null handler then is there any reason
not
> to add code to set that automatically (to std::terminate) and possibly
add
> code to do something sane when null is passed in?

Others may have a better answer than me, but I am not certain it's
worth the added complexity for deprecated functionality.

I think given the dependency on libc++abi I tend to agree. Whilst I

dislike coupling/dependencies, it's pretty minor and given it's deprecated
even more so. Thanks for the input!