Demonstrates the Result<T> pattern for type-safe error handling.
Demonstrates the Result<T> pattern for type-safe error handling.Covers basic Result usage, value_or / unwrap_or defaults, pattern matching, monadic operations (map, and_then, or_else), error recovery, and exception wrapping with try_catch. Provides real-world examples of division and file-reading functions that return Result<T> instead of throwing exceptions.
#include <iostream>
#include <fstream>
#include <string>
if (b == 0) {
return make_error<int>(
error_codes::INVALID_ARGUMENT,
"Division by zero",
"math_module"
);
}
return ok(a / b);
}
if (path.empty()) {
return make_error<std::string>(
error_codes::INVALID_ARGUMENT,
"Path cannot be empty",
"file_module"
);
}
std::ifstream file(path);
if (!file.is_open()) {
return make_error<std::string>(
error_codes::NOT_FOUND,
"File not found: " + path,
"file_module"
);
}
std::string content((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
}
auto pos = expr.find('/');
if (pos == std::string::npos) {
return make_error<int>(
error_codes::INVALID_ARGUMENT,
"Invalid expression format",
"parser"
);
}
try {
int a = std::stoi(expr.substr(0, pos));
int b = std::stoi(expr.substr(pos + 1));
} catch (const std::exception& e) {
return make_error<int>(
error_codes::INVALID_ARGUMENT,
std::string("Parse error: ") + e.what(),
"parser"
);
}
}
std::cout << "=== Result Pattern Examples ===\n\n";
std::cout << "1. Basic division:\n";
if (result1.is_ok()) {
std::cout << " 10 / 2 = " << result1.value() << "\n";
}
if (result2.is_err()) {
std::cout <<
" Error: " <<
err.message
<<
" (code: " <<
err.code <<
")\n";
}
std::cout << "\n2. Using value_or:\n";
auto value =
divide(10, 0).unwrap_or(-1);
std::cout << " 10 / 0 with default -1 = " << value << "\n";
std::cout << "\n3. Pattern matching:\n";
if (result3.is_ok()) {
std::cout << " Success: " << result3.unwrap() << "\n";
} else {
std::cout << " Failed: " << result3.error().message << "\n";
}
std::cout << "\n4. Monadic operations:\n";
auto result4 =
divide(100, 5);
auto doubled = result4.map([](int x) { return x * 2; });
if (doubled.is_ok()) {
std::cout << " (100 / 5) * 2 = " << doubled.value() << "\n";
}
std::cout << "\n5. Chaining operations:\n";
auto chain_result =
divide(50, 5)
.and_then([](
int x) {
return divide(x, 2); });
if (chain_result.is_ok()) {
std::cout << " (50 / 5) / 2 = " << chain_result.value() << "\n";
}
std::cout << "\n6. Error recovery:\n";
auto recovered =
divide(10, 0)
std::cout << " 10 / 0 with recovery = " << recovered.value() << "\n";
std::cout << "\n7. Exception wrapping:\n";
auto wrapped = try_catch<int>([]{
throw std::runtime_error("Something went wrong");
return 42;
}, "example_module");
if (wrapped.is_err()) {
std::cout <<
" Caught exception: " <<
err.message <<
"\n";
}
std::cout << "\n=== Examples completed ===\n";
return 0;
}
Result type for error handling with member function support.
const error_info & error() const
Get error reference.
Result< T > ok(T value)
Create a successful result.
VoidResult err(const error_info &error)
Factory function to create error VoidResult.
Umbrella header for Result<T> type and related utilities.
Result< int > parse_and_compute(const std::string &expr)
Result< std::string > read_file(const std::string &path)
Result< int > divide(int a, int b)
Standard error information used by Result<T>.