[#MRDOCS_CHECK] = MRDOCS_CHECK :mrdocs: Check an existing expected‐like value and propagate its error. == Synopsis Declared in `<mrdocs/Support/Error/Expected.hpp>` [source,cpp,subs="verbatim,replacements,macros,-callouts"] ---- #define MRDOCS_CHECK(...) ---- == Description Tests a value you already have and, if it failed, makes the enclosing function return `Unexpected`. Unlike `MRDOCS_TRY`, the value isn't moved from or bound to a name. The enclosing function must return an xref:mrdocs/Expected.adoc[`mrdocs::Expected`] (or anything constructible from `Unexpected`). A value counts as failed when it is an xref:mrdocs/Expected.adoc[`mrdocs::Expected`] without a value, a failed xref:mrdocs/Error.adoc[`mrdocs::Error`], an empty container or string, or anything that converts to `false` (pointers, `std::optional`, conditions). See `MRDOCS_TRY` for the details. The macro takes one or two arguments. The equivalent code below is simplified: `failed` and `error` are `::mrdocs::detail::failed` and `::mrdocs::detail::error`. With one argument, it forwards the error the value already holds: [,cpp] ---- Expected p = parsePort(port); MRDOCS_CHECK(p); ---- is equivalent to: [,cpp] ---- Expected p = parsePort(port); if (failed(p)) { // !p, since p is an Expected return Unexpected(error(p)); // p.error() } ---- A failed xref:mrdocs/Expected.adoc[`mrdocs::Expected`] or xref:mrdocs/Error.adoc[`mrdocs::Error`] is forwarded as is, a failed container becomes the error `"Empty value"`, and a value that converts to `false` becomes `"Invalid value"`. With two arguments, it returns a new error built from the second argument instead: [,cpp] ---- MRDOCS_CHECK(!host.empty(), "empty host"); ---- is equivalent to: [,cpp] ---- if (failed(!host.empty())) { // the condition is false return Unexpected(Error("empty host")); } ---- The second argument can be anything xref:mrdocs/Error.adoc[`mrdocs::Error`] is constructible from, such as a non‐empty string, a `std::error_code`, or another xref:mrdocs/Error.adoc[`mrdocs::Error`]. It's only evaluated when the check fails, so building a message there is cheap on success: [,cpp] ---- MRDOCS_CHECK(*p < 65536, formatError("port {} out of range", *p)); ---- Pass a message when `"Empty value"` or `"Invalid value"` wouldn't help the caller. Things to keep in mind: * Use it only inside a function body, and end it with a semicolon. * In the one‐argument form, a failed argument is evaluated twice, once to test it and once to read its error, so pass a named value rather than a call like `MRDOCS_CHECK(parse(s))`. Use `MRDOCS_TRY` for that. The two‐argument form evaluates it once. * The expansion is two statements. Put braces around it when it's the body of an `if`, `else`, or loop. * Wrap an argument in parentheses if it has a top‐level comma, such as a template argument list. * The two‐argument form names `Error` without qualification. Outside namespace `mrdocs`, bring it in with `using mrdocs::Error;`. To return early from a function that doesn't return an xref:mrdocs/Expected.adoc[`mrdocs::Expected`], use `MRDOCS_CHECK_OR`. [.small]#Created with https://www.mrdocs.com[MrDocs]#