Boost logo

Boost :

Subject: Re: [boost] Error handling libraries and proposals
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-07-10 23:19:14

On 10/07/2017 22:06, Emil Dotchevski via Boost wrote:
> On Mon, Jul 10, 2017 at 1:36 PM, Niall Douglas via Boost <
> boost_at_[hidden]> wrote:
>> outcome<void, void> would equal outcome<void, void, std::exception_ptr>.
>> Such an object can store a void or an exception_ptr. Or rather, have the
>> state of a void or an exception_ptr.
> So, if I understand correctly, the second void means exception_ptr? Why
> isn't it outcome<void,exception_ptr>? What are the semantic differences
> between e.g. expected<int,exception_ptr> and outcome<int,void>?

Are you confusing result and outcome?

result<T, EC>

outcome<T, EC, E|P>

The default template parameters give exactly the same as with v1. But if
say you chose `result<int, long>` or `outcome<int, long, std::string>`
then that works too.

>>> , but for Outcome v2 the new values are:
>>> yes, yes, yes, yes, no, yes, yes, yes.
>>> To me, your note that Outcome is struct-like rather than variant-like
>>> means that it does not have strict value-or-error semantics, so the last
>>> one would be "no".
>> Unless you enable the positive status support manually, a strict
>> enforcement of value or error is made.
> Ah, so this means that it is optional, like in Noexcept. I'll reflect that
> in the comparison table.

Eh, well, it defaults to strict enforcement of either, it can only be
different if you change a macro. And as the code matures I may make the
strict enforcement mandatory.

>>> Also, could you expand on how Outcome can propagate
>>> errors from a C-style callback or across language boundaries? I'm
>>> referring to use cases like these:
>> I specifically personally need result to be C layout compatible so AFIO
>> can have C SWIG bindings. Outcome v1 was C layout compatible too, but v2
>> is even more so because it's just a struct of the form:
>> struct
>> {
>> T value;
>> unsigned flags;
>> EC error;
>> };
>> ... and bit 0 of the unsigned means a T is present, and bit 2 means an
>> EC is present.
> It seems that here you are making the case I've been making, that in
> general std::error_code is not sufficient, that an error-handling library
> must be able to propagate errors of user-defined types, and not only
> through an exception_ptr.

I did take into account your feedback during the review, yes, and I've
definitely thrown you some meat in v2.

> I also think it is a good idea to be
> C-compatible, but from the above it isn't clear to me how that works. Could
> you please post a complete example, specifically how can outcome<T>
> propagate errors from a C (not C++) API?

That it cannot do. You could store it into TLS the same as you're doing
behind the scenes though. Outcome v2 is far more barebones than v1 was.
It does pretty much nothing above the absolute bare minimum.

> That said, if you look at the example I linked, you'll see that it is about
> more than just being C-layout compatible, but also being able to propagate
> an error from a third-party C-style callback which does not return your
> struct. In case I'm missing something, could you post the outcome<T>
> version of the example I linked?

You'd declare some TLS storage, same as you do internally, and reference
that. So say:

static thread_local result<void, do_work_error> state;

int do_work( lua_State * L ) noexcept {
    bool success=rand()%2;
    if( success )
        return lua_pushnumber(L,42), 1;
        state = do_work_error{};
        return lua_error(L);
result<int, do_work_error> call_lua( lua_State * L ) noexcept {
    lua_getfield( L, LUA_GLOBALSINDEX, "call_do_work" );
    if( int err=lua_pcall(L,0,1,0) ) {
        return state;
    else {
        int answer=lua_tonumber(L,-1);
        return answer;

Which is almost as succinct as yours.


ned Productions Limited Consulting

Boost list run by bdawes at, gregod at, cpdaniel at, john at