https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119197

            Bug ID: 119197
           Summary: [feat req] `std::expected` should be nodiscard
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: arthur.j.odwyer at gmail dot com
  Target Milestone: ---

See https://quuxplusone.github.io/blog/2024/12/08/should-expected-be-nodiscard/
and
https://www.reddit.com/r/cpp/comments/1h9u4us/should_stdexpected_be_nodiscard/
(notice the top comment is by STL saying "no," and his next comment reverses
his position to "strongly yes") —

    using Eint = std::expected<int, std::error_code>;
    Eint f_or_error() noexcept;

It is invariably problematic to discard the result of a function that uses
`expected` for error handling. That's the equivalent of enclosing an
exception-throwing function call in `try { ... } catch(...){}`, discarding any
error condition; but the language allows it to happen without any ceremony. It
should of course still be possible to write the ceremony explicitly—

    (void)f_or_error();

The way we make this happen is by marking `std::expected` as [[nodiscard]].

Microsoft STL has already marked it, in
https://github.com/microsoft/STL/pull/5174

martinmoene/expected-lite has already marked it.

libc++ has fixed their tests to keep working when `std::expected` is marked
nodiscard, although their own `std::expected` is not yet marked.

Microsoft STL's commit *also* marked all the exception types, which (if
libstdc++ did the same) would immediately fix #116866.

---

In fact, if you're ever asked "When should I use variant<T,U> and when should I
use expected<T,U>, given that they are physically equivalent?" — the answer is
"expected<T,U> is designed for error-handling and is (should be) nodiscard;
variant<T,U> is more general-purpose and is not nodiscard." The
error-handlingness (i.e. the should-be-nodiscardness) of `expected` is pretty
much its single defining characteristic.

---

jwakely was initially concerned that compiler bug #85973 might have rendered
such a marking completely moot, so it was a low priority in libstdc++; but my
understanding is that this concern has been resolved: #85973 is triggered only
in circumstances much more obscure than jwakely originally thought, and in fact
marking std::expected as [[nodiscard]] would have an immediate beneficial
effect in (1) ensuring error returns are handled correctly, and (2) aligning
libstdc++'s diagnostics with MS STL's in this specific area.

Reply via email to