Check an existing expected-like value and propagate its error.
Declared in <mrdocs/Support/Error/Expected.hpp>
#define MRDOCS_CHECK(...)
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 mrdocs::Expected (or anything constructible from Unexpected).
A value counts as failed when it is an mrdocs::Expected without a value, a failed 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:
Expected<int> p = parsePort(port);
MRDOCS_CHECK(p);
is equivalent to:
Expected<int> p = parsePort(port);
if (failed(p)) { // !p, since p is an Expected
return Unexpected(error(p)); // p.error()
}
A failed mrdocs::Expected or 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:
MRDOCS_CHECK(!host.empty(), "empty host");
is equivalent to:
if (failed(!host.empty())) { // the condition is false
return Unexpected(Error("empty host"));
}
The second argument can be anything mrdocs::Error is constructible from, such as a non-empty string, a std::error_code, or another mrdocs::Error. It's only evaluated when the check fails, so building a message there is cheap on success:
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 mrdocs::Expected, use MRDOCS_CHECK_OR.