On 31/05/2017 11:31, Vicente J. Botet Escriba via Boost wrote:
Does none_t mean success or failure? For what I see it means failure as it is not the result of value(). In addition it default construct to none_t.
The mental model for me is variant<optional<T>, error_code, exception_ptr>> m_storage;
Surely it is actually: variant<monostate, T, error_code, exception_ptr> std::monostate at the front of the typelist gives std::variant default-construct-to-empty semantics.
Perhaps this could even be exposed even more so that user code could explicitly provide both a value and an error -- think "here's a value, but it was truncated" or "here's the 5 values you asked for, but there's more", both fairly common in system APIs. Or for things like ambiguous matches where you still return the most likely candidate. Or dictionary insertion (duplicate key, but here's the value that's already there). Or many more such examples. (Though obviously in this case value() couldn't call ensure(). But that should make some people happy.)
This corresponds to the status_value [1] model where you store the reason why you don't have a value or why you have it and an optional<value>. As described by L. Crowl in [2], there are use cases for status_value, expected and exceptions.
Personally speaking, I have not found Lawrence's status_value proposal sufficiently value-adding over returning a std::pair to be worth implementing. Also, the STL already uses std::pair throughout for status returns, it's the convention, though I will agree to use it is mildly clunky e.g. unordered_map::insert().first. Now, that said, if expected<T, E> and status_value<Status, Value> could be combined into a single object, that I can see significant value in. It's something I've often pondered for Outcome as well because it could, if done right, let me eliminate error_code_extended. The main thing which has stopped me is the potential confusion. For example, right now we have result<T> which can be empty|T|error_code_extended. If I instead made: template<class T, class Payload = void> class result; Now result could be (empty|T|std::error_code U Payload). But if this review to date with 600+ emails has been complicated, imagine a review of such a payload-carrying result object? std::error_code + payload is obvious. But, what does an empty state + payload mean? I have no idea. Indeed, what does a T state + payload mean? I guess that is Lawrence's status_value<> use case, but the problem is that the Payload type is fixed between variant states of empty|T|std::error_code and that surely is not particularly useful, you'd want different payload types with each of T or std::error_code. That's why I didn't implement it. Still, I'd be interested in what people think. The other option is empty|T|status_value<std::error_code, Payload>, that would make more sense, but at the potential cost of bloating the stack significantly which could surprise end users in a way error_code_extended can not. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/