
A modern C++23 library providing robust error handling utilities and abstractions built around std::expected
and std::error_code
.
This library provides tools to simplify error handling, improve code readability, and ensure robust error management.
Features
- Error handling with context using
Result<T>
type (based on std::expected
).
- System error code integration with
std::error_code
and std::error_condition
.
- Exception handling utilities with automatic conversion to error codes.
- Convenient error handling for C system calls and errno.
- Custom error categories and conditions.
- Support for chaining error operations.
- Zero overhead abstractions.
- Support for exception-safe code.
- Monadic operations for functional composition on
Result<T>
, from std::expected
.
- Lightweight and easy to integrate into existing projects.
Thread Safety
This library is designed to be thread-safe.
However, the thread safety of your code depends on how you use the library.
If you share Result<T>
objects across threads, ensure proper synchronization.
Requirements
- C++23 compatible compiler (GCC 14.2.0+ or Clang 19+) with a supported implementation of the C++ standard library, such as libstdc++ 14.2.0 (bundled with GCC C++ compiler).
The library currently supports only UNIX-like systems (Linux, macOS, etc.). Windows support is not guaranteed but will be added in the future.
Installation
The library is header-only, so you can easily include it in your project.
Option 1: Copy the header files (the simplest method)
- Download the header files from the include/ directory of the repository.
- Place them in your project's include directory.
- Include the headers in your source files as needed.
Option 2: Use CMake FetchContent module (recommended for projects already using CMake)
If your project uses CMake, you can use the FetchContent module to include this library as a dependency.
In your CMakeLists.txt
, add the following lines:
include(FetchContent)
FetchContent_Declare(
cpp_error_utils
GIT_REPOSITORY https://github.com/dr8co/cpp_error_utils.git
GIT_TAG main
)
FetchContent_MakeAvailable(cpp_error_utils)
target_link_libraries(your_target_name PRIVATE cpp_error_utils::cpp_error_utils)
Option 3: System-wide installation
Prebuilt binaries are available at the release page.
You can download the latest release and install it with your package manager.
If you want to manually build and install the library system-wide, you can do so by following these steps:
Clone the repository:
git clone https://github.com/dr8co/cpp_error_utils.git
Navigate into the cloned directory:
Build and install the library:
mkdir build && cd build
cmake ..
cmake --build . --config Release
cmake --install . --config Release # might need sudo
The following CMake options are available:
CPP_ERR_BUILD_EXAMPLES
- Build example programs (ON by default)
CPP_ERR_BUILD_TESTING
- Build tests (ON by default)
CPP_ERR_BUILD_DOC
- Build documentation (OFF by default)
CPP_ERR_PACKAGE
- Create installation package (OFF by default)
Usage Examples
Include the necessary headers in your C++ files:
Error handling utilities for C++ applications.
Basic Result Type Usage
#include <string_view>
#include <print>
#include <filesystem>
namespace fs = std::filesystem;
Result<void> print_file_details(std::string_view file_name) {
std::error_code ec{};
const fs::path file_path{file_name};
const auto status = fs::status(file_path, ec);
if (ec) {
ec, std::format("Failed to determine the attributes of '{}'", file_name)
});
}
if (!fs::exists(status)) {
std::errc::no_such_file_or_directory, std::format("File '{}' does not exist.", file_name)
});
}
std::print("{}", fs::absolute(file_path).string());
switch (status.type()) {
case fs::file_type::regular:
std::println(" is a regular file.");
break;
case fs::file_type::directory:
std::println(" is a directory.");
break;
case fs::file_type::fifo:
std::println(" is a named IPC pipe.");
break;
case fs::file_type::block:
std::println(" is a block device.");
break;
case fs::file_type::socket:
std::println(" is a named IPC socket.");
break;
case fs::file_type::symlink:
std::println(" is a symbolic link.");
break;
case fs::file_type::character:
std::println(" is a character device.");
break;
case fs::file_type::unknown:
std::println(" has 'unknown' type.");
break;
case fs::file_type::none:
std::println(" has 'not-evaluated-yet' type");
break;
default:
std::println(" has an implementation-defined type.");
}
std::print("File permissions: ");
const auto file_perms = status.permissions();
auto show = [=](const char op, const fs::perms perm) {
std::print("{}", fs::perms::none == (perm & file_perms) ? '-' : op);
};
show('r', fs::perms::owner_read);
show('w', fs::perms::owner_write);
show('x', fs::perms::owner_exec);
show('r', fs::perms::group_read);
show('w', fs::perms::group_write);
show('x', fs::perms::group_exec);
show('r', fs::perms::others_read);
show('w', fs::perms::others_write);
show('x', fs::perms::others_exec);
std::println();
return {};
}
int main(int argc, char *argv[]) {
if (argc < 2) {
std::println("Usage: {} <file>", argv[0]);
return 1;
}
auto res = print_file_details(argv[1])
.or_else(
std::println(stderr,
"An error occurred: {}", err.
message());
return {};
}
);
return 0;
}
A wrapper class for system error codes with additional context.
Definition error_utils.hpp:332
constexpr std::string message() const
Get the error message including context if available.
Definition error_utils.hpp:429
std::expected< T, Error > Result
A specialization of std::expected for the Error type.
Definition error_utils.hpp:483
Exception Handling
int main() {
return 42;
});
if (result) {
std::println("Success: {}", result.value());
} else {
std::println("Error: {}", result.error().message());
}
return 0;
}
Result< int > IntResult
Result type for integers (std::expected<int, Error>)
Definition error_utils.hpp:491
constexpr auto try_catch(Func &&func, std::string_view context={}) -> Result< R >
Execute a function and catch common exceptions, converting them to errors.
Definition error_utils.hpp:689
System Call Error Handling
IntResult create_directory(
const std::string& path) {
[&] noexcept { return mkdir(path.c_str(), 0755); },
std::format("Failed to create directory '{}'", path)
);
}
Result< int > IntResult
Result type for integers (std::expected<int, Error>)
Definition error_utils.hpp:491
IntResult invoke_with_syscall_api(Func &&func, const std::string_view error_context={}) noexcept
Execute a function that may set errno, capturing the result and any error.
Definition error_utils.hpp:666
Check out more examples for additional usage patterns.
Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository.
- Create a new branch for your feature or bug fix.
- Submit a pull request with a detailed description of your changes.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Contact
For questions or feedback, feel free to open an issue or contact me directly at dr8co@duck.com.