MRDOCS_CHECK_OR

Check a value and return early if it failed.

Synopsis

#define MRDOCS_CHECK_OR(…​)

Description

Use this in functions that don't return an mrdocs::Expected. If the value failed, the enclosing function returns the second argument, or just returns when there's no second argument. No error is produced. See MRDOCS_TRY for what counts as failed.

The macro takes one or two arguments. The equivalent code below is simplified: failed is ::mrdocs::detail::failed. The examples use this type:

struct Node
{
    Node* parent = nullptr;
    std::string name;
    int n = 0;
};

With one argument, it does a plain return;, so it only works in a function that returns void:

void
rename(Node* node, std::string name)
{
    MRDOCS_CHECK_OR(node);
    node->name = std::move(name);
}

is equivalent to:

void
rename(Node* node, std::string name)
{
    if (failed(node)) {  // !node, since it's a pointer
        return;
    }
    node->name = std::move(name);
}

With two arguments, it returns the second argument instead:

Node const*
grandparent(Node const& node)
{
    MRDOCS_CHECK_OR(node.parent, nullptr);
    return node.parent->parent;
}

is equivalent to:

Node const*
grandparent(Node const& node)
{
    if (failed(node.parent)) {
        return nullptr;
    }
    return node.parent->parent;
}

The second argument can be anything convertible to the function's return type, including a braced {} for a default value:

std::optional<int>
count(Node const* node)
{
    MRDOCS_CHECK_OR(node, std::nullopt);
    MRDOCS_CHECK_OR(node->n > 0, {});  // returns an empty optional
    return node->n;
}

The checked value is evaluated once, so a call expression is fine here. The return value is only evaluated when the check fails.

Things to keep in mind:

  • Use it only inside a function body, and end it with a semicolon.

  • The one‐argument form only works in a function that returns void. The two‐argument form needs a value convertible to the function's return type.

  • 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 (std::pair<int, int>{}).

Created with MrDocs