Boost logo

Boost :

Subject: [boost] [outcome] New proposed factory API as per review feedback
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-05-24 21:11:49


>> Earlier rounds of feedback from Reddit convinced me that customising
>> basic_monad is a very niche enterprise. Very, very few users of Outcome
>> will want to do that.
>
> I agree with this assumption. But if this is the case, I think you should
> not expose in the reference section of the documentation that outcome<> has
> a base class. As per your explanation, it is just an implementation detail.
> I am referring to this page:
> https://ned14.github.io/boost.outcome/classboost_1_1outcome_1_1v1__xxx_1_1outcome.html

I didn't want to be accused of misrepresenting the reference
documentation. Actually, I am surprised nobody has yet accused me of
doing so as the doxygen reference docs refer to classes which don't
exist as classes e.g. outcome, result, option.

>> How about these for the narrow contract editions of outcome<T>,
>> result<T> and option<T>:
>>
>> - outcome_u<T>
>> - result_u<T>
>> - option_u<T>
>
> But I mistakenly took it as saying "do it yourself". You were proposing
> more of precooked "transports". Sorry.

Yes I was.

In fact, I am increasingly thinking that a consensus position could be
this type factory template:

// What to default construct to
enum class default_to
{
  none,
  T,
  EC,
  E
};

// How much empty state to implement
enum class emptiness
{
  never, // imposes restrictions on T, EC, E
  formal, // formal empty state
  tolerant // empty state iff EC and E don't have nothrow move construction
};

// How narrow or wide the observers will be
enum class observers
{
  narrow, // accessing not the current state = reinterpret_cast
  wide, // default actions already described earlier this review
  single_shot // you can observe state precisely once only
};

// Replacement for basic_monad
template<
  class T, // what .value() returns, or void
  class EC, // what .error() returns, or void
  class E, // what .exception() returns, or void
  default_to default_to_config,
  emptiness empty_config,
  observers observers_config
> class outcome_impl;

// Outcome as apparently desired by reviewers
template<class T> using outcome = outcome_impl<
  T,
  error_code_extended,
  std::exception_ptr,
  default_to::none, // default constructed instance =
reinterpret_cast uninitialised memory
  emptiness::never, // Never possible to be empty, not ever
  observers::narrow // reinterpret_cast all observers
>;

// Result as apparently desired by reviewers
template<class T> using result = outcome_impl<
  T,
  error_code_extended,
  void, // there is still a .exception(), but it returns
void and is not usable
  default_to::none, // default constructed instance =
reinterpret_cast uninitialised memory
  emptiness::never, // Never possible to be empty, not ever
  observers::narrow // reinterpret_cast all observers
>;

> Regarding your suggestion to use `expected<>`, I could use `expected<T,
> error_code_extended>` and this would get me close to `result<T>`, but I get
> no counterpart for `outcome<T>`. Or are you really proposing to add
> `outcome_u<T>` to collection?

Yes I was.

See what you think of the proposed API above. We supply a precanned
outcome<T> and result<T> template alias, but end users can template
alias any configuration they like.

>> If that's the consensus opinion, that's a fair bit of work to implement
>> and I'm fairly sure it will affect compile times, but I am open to it.
>> The single implementation-many personality design I chose is very
>> amenable to such knobs for twiddling.

I may be able to keep compile times low using extern template and
supplying a static library to be linked against. But I believe the above
will punish header only usage badly. I'll do my best.

Niall

-- 
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/

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