Expected
ll/api/Expected.h Β· Common
Overview
The Expected module provides LeviLamina's error handling primitives: Expected<T> (a value-or-error type based on nonstd::expected), Error (a polymorphic error container), and helper functions for creating and propagating errors.
| Header |
Description |
ll/api/Expected.h |
Expected<T>, Error, ErrorInfoBase, and factory functions |
Key Types
Expected\<T>
| C++ |
|---|
| namespace ll {
template <class T = void>
using Expected = nonstd::expected<T, ll::Error>;
}
|
Expected<T> β holds either a value of type T or an ll::Error
Expected<> β alias for Expected<void>, represents success or error without a value
Error
A move-only error container wrapping a polymorphic ErrorInfoBase.
| C++ |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | namespace ll {
class Error {
public:
Error() noexcept = default;
Error(std::unique_ptr<ErrorInfoBase> info) noexcept;
explicit operator bool() const noexcept; // true if error exists
std::string message() const noexcept;
template <class T> bool isA() noexcept;
template <class T> T& as() noexcept;
Error& join(Error) noexcept;
Error const& log(io::Logger&, io::LogLevel = io::LogLevel::Error) const noexcept;
Error const& log(CommandOutput&, CommandOutputMessageType = CommandOutputMessageType::Error) const noexcept;
};
}
|
ErrorInfoBase
Abstract base class for error details. Subclass this to create custom error types.
| C++ |
|---|
| namespace ll {
class ErrorInfoBase {
public:
virtual ~ErrorInfoBase();
virtual std::string message() const noexcept = 0;
};
}
|
Built-in Error Types
| Type |
Description |
StringError |
Wraps a std::string message |
ErrorCodeError |
Wraps a std::error_code |
Factory Functions
| C++ |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | namespace ll {
// Create Unexpected from error subclass
template <std::derived_from<ErrorInfoBase> T, class... Args>
Unexpected makeError(Args&&... args) noexcept;
// Shorthand for string errors
Unexpected makeStringError(std::string str) noexcept;
// Shorthand for error_code errors
Unexpected makeErrorCodeError(std::error_code ec) noexcept;
Unexpected makeErrorCodeError(std::errc ec) noexcept;
// Capture current exception as error
Unexpected makeExceptionError(std::exception_ptr const& = std::current_exception()) noexcept;
// Forward an existing error
Unexpected forwardError(Error& err) noexcept;
}
|
Usage
Returning Errors
| C++ |
|---|
| #include "ll/api/Expected.h"
ll::Expected<int> divide(int a, int b) {
if (b == 0) {
return ll::makeStringError("Division by zero");
}
return a / b;
}
|
Handling Errors
| C++ |
|---|
| #include "ll/api/Expected.h"
#include "ll/api/io/Logger.h"
void example(ll::io::Logger& logger) {
auto result = divide(10, 0);
if (!result) {
result.error().log(logger);
return;
}
logger.info("Result: {}", *result);
}
|
Custom Error Types
| C++ |
|---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | #include "ll/api/Expected.h"
struct FileNotFoundError : ll::ErrorInfoBase {
std::string path;
FileNotFoundError(std::string path) : path(std::move(path)) {}
std::string message() const noexcept override {
return "File not found: " + path;
}
};
ll::Expected<std::string> readFile(std::string const& path) {
// ...
return ll::makeError<FileNotFoundError>(path);
}
void handleError() {
auto result = readFile("missing.txt");
if (!result) {
if (result.error().isA<FileNotFoundError>()) {
auto& err = result.error().as<FileNotFoundError>();
// Access err.path
}
}
}
|
Propagating Errors
| C++ |
|---|
| #include "ll/api/Expected.h"
ll::Expected<int> computeSum(int a, int b) {
auto x = divide(a, 2);
if (!x) return ll::forwardError(x.error());
auto y = divide(b, 3);
if (!y) return ll::forwardError(y.error());
return *x + *y;
}
|
Void Expected
| C++ |
|---|
| #include "ll/api/Expected.h"
ll::Expected<> initialize() {
// Do something that might fail
return {}; // Success
}
ll::Expected<> initializeWithError() {
return ll::makeStringError("Initialization failed");
}
|
- IO & Logger β
Error::log() outputs to a Logger
- Mod β Mod lifecycle callbacks return
Expected<>