Boost logo

Boost :

Subject: Re: [boost] [outcome] High level summary of review feedback accepted so far
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2017-05-29 07:23:29


On 28/05/2017 10:46, Niall Douglas wrote:
>>> I would agree. But well, we were outvoted. And that probably means
>>> rejection of this library, as the presented library does not implement
>>> what the majority want (yet).

Just to clarify the meaning, since I'm not especially fluent in
standardese: by "narrow contract" you mean "has UB if you don't include
external checks", correct? I really don't like that even being an
option in a type intended to improve error handling.

> I personally think I'll have very little use for the narrow contract
> varieties, but I've been convinced by the non-empty-capable vs
> empty-capable distinction because it means that my public API functions
> can specify via the type they return whether an empty return is possible
> or not, thus more accurately specifying their public contract. That, and
> the fact I can still use a receiving empty-capable variety for detecting
> when loops haven't found what they were looking for etc I find very
> compelling.

Doesn't that make things more complicated, though? Library A uses one
flavour of it and library B uses a different flavour; how do they
interoperate? (I know both can coexist due to namespacing and other
things, but still if one method calls the other there has to be some
kind of handover of the return value.)

For that matter, what happens when a method in library A (using the
guaranteed-never-empty flavour) calls a method in library B (using the
empty-by-default flavour)? Can they put the return value into one of
their never-empty outcomes (but then what if it's empty?) or do they
have to work with the might-be-empty outcome type that's foreign to
their own code and way they want to do things, and thus more likely to
be used incorrectly?

Typedefs can sort out the differences to a certain extent, but then you
need to remember to use the right one with each library (either getting
unexpected behaviour or the compiler yelling at you when incorrect,
depending on implementation, neither of which is particularly
desirable), and there's possible interoperability issues for storing the
results from multiple libraries into a single vector, for example.

I know this entire discussion has proved that it's hard to find
consensus on the One True Wayâ„¢, but I'm inclined to believe that it may
still be important to do so when trying to define a vocabulary type.

> People are getting hung up on the multitude of types. They're just API
> personalities onto an identical implementation. They're just different
> ways of speaking to the same variant storage, so basically we are using
> the C++ type system like a pair of glasses onto the exact same view,
> with well defined rules for changing which glasses you're wearing as
> demand presents.

Perhaps this answers some of my questions above with "it just works",
but perhaps also these sorts of things should be clarified in the docs?

What about interop between a v1 outcome and a v2 outcome? That's no
longer an identical implementation.


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