What about result<udt, void>? This is absolutely legal, it means that no error state is returned when there was an error. This can help with clarifying in code the use of std::optional<udt> as Optional more logically means value-or-nothing, not necessarily value-or-error.

In contrast, result<udt, void> unambiguously does mean success-or-failure, just with an unspecified cause of failure.

Outcome’s default action for EC = void is to call std::terminate:

  struct udt
    int a{0};
    explicit udt(int _a)
        : a(_a)
    udt() = default;
    int operator*() const { return a; }
  result<udt, void> res(in_place_type<void>);

  // What happens here? What exception type is thrown?
    std::cout << *res.value() << std::endl;
  catch(const std::exception &e)
    std::cerr << "Exception thrown was " << e.what() << std::endl;
View this code on Github

Running this yields:

ned@lyta:~/outcome/build_posix$ bin/outcome-snippets_void_terminate
terminate called without an active exception
Aborted (core dumped)