The constexpr variables are already there. So basically do we prefer:
1. .ensure_empty(), .ensure_value(), .ensure_error() and .ensure_exception()
2. Or .ensure(empty), .ensure(value), .ensure(error) and .ensure(exception)
I figure the latter looked nicer. It's same difference to the compiler, simple overload matching is constant time.
But why have them at all, rather than just calling value(), error(), etc and discarding the return value? They're also constexpr.
Code correctness auditing. You can prefix o.value() with a (void) of course, but I think the potential [[nodiscard]] on the reference returning observers might be a gain (note that the end user applying [[nodiscard]] to the types used won't work because of the reference return).
Also, what code patterns would lead to wanting to do that frequently anyway? Given that the whole point is to transport a value or an error, it seems odd to have code paths that want to throw if a value or error was not produced but then not actually care what the "right" thing was.
The default actions are extremely useful at an outcome-to-c++-exception boundary where low level Outcome returning code is used by higher level code exclusively using C++ exceptions. The default actions save considerable boilerplate checking state by hand etc. Anyone who has used AFIO v2 will know exactly what I mean. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/