MRDOCS_TRY
Evaluate an expected‐like expression and propagate its error.
Synopsis
Declared in <mrdocs/Support/Error/Expected.hpp>
#define MRDOCS_TRY(…)
Description
The expression is evaluated once and stored in a hidden local. If it failed, the enclosing function returns Unexpected with its error. Otherwise the value is moved into the variable you name, if any. The enclosing function must return an mrdocs::Expected (or anything that can be constructed from Unexpected).
A value counts as failed when it is:
-
an
mrdocs::Expectedwithout a value (its error is propagated), -
a failed
mrdocs::Error(the error itself is propagated), -
anything with an
empty()member that returnstrue(the error isError("Empty value")), -
anything that converts to
false(the error isError("Invalid value")).
Values that match none of these never count as failed.
The macro takes one, two, or three arguments. The equivalent code below is simplified: the hidden local is really named expected_result_<line>, and failed/`error` are ::mrdocs::detail::failed and ::mrdocs::detail::error.
With one argument, it checks the expression and discards the value:
MRDOCS_TRY(checkReadable(path));
is equivalent to:
auto tmp = checkReadable(path);
if (failed(tmp)) {
return Unexpected(error(tmp));
}
This form also works on values that aren't an mrdocs::Expected. An empty container fails with "Empty value", and a value that converts to false fails with "Invalid value":
MRDOCS_TRY(findInputs(dir)); // a container
MRDOCS_TRY(isConfigured()); // a bool
With two arguments, it declares a variable and moves the value into it:
MRDOCS_TRY(std::string text, readFile(path));
is equivalent to:
auto tmp = readFile(path);
if (failed(tmp)) {
return Unexpected(error(tmp));
}
std::string text = *std::move(tmp);
The first argument can also name a variable that already exists, in which case the value is assigned to it:
MRDOCS_TRY(text, trim(text));
is equivalent to:
auto tmp = trim(text);
if (failed(tmp)) {
return Unexpected(error(tmp));
}
text = *std::move(tmp);
With three arguments, it works like the two‐argument form but replaces the error with your own message:
MRDOCS_TRY(int n, parseInt(text), "count isn't a number");
is equivalent to:
auto tmp = parseInt(text);
if (failed(tmp)) {
return Unexpected(Error("count isn't a number"));
}
int n = *std::move(tmp);
Things to keep in mind:
-
It expands to several statements, so use it only in a function body, and put braces around it when it's the body of an
if,else, or loop. -
The hidden local is named after
LINE, so you can't use it twice on the same line (or twice inside one line of another macro). -
Like any statement, it needs a trailing semicolon.
-
The expression is stored with
auto, so an lvalue argument is copied, not moved. -
The two‐ and three‐argument forms read the value with
*, so they need a type with a value to dereference, such asExpected<T>. Use the one‐argument form forExpected<void>,mrdocs::Error, containers, andbool. -
The three‐argument form discards the original error and returns
Error(msg), somsgcan be anythingmrdocs::Erroris constructible from, such as a non‐empty string. It's only evaluated on failure.Erroris named unqualified, so it needsmrdocs::Errorto be visible (inside namespacemrdocs, or afterusing mrdocs::Error;).
To unpack the value into several names, use MRDOCS_TRY_BIND.
Created with MrDocs