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_1ou...
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
` 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/