MRDOCS_CHECK

Check an existing expected‐like value and propagate its error.

Synopsis

#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 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.

Created with MrDocs