cpp_error_utils 1.0.0
C++ error handling utilities
Loading...
Searching...
No Matches
error_utils.hpp
Go to the documentation of this file.
1// MIT License
2//
3// Copyright (c) 2025 Ian Duncan
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23
31
32#pragma once
33
35#define CPP_ERROR_UTILS_VERSION_MAJOR 1
36
38#define CPP_ERROR_UTILS_VERSION_MINOR 0
39
41#define CPP_ERROR_UTILS_VERSION_PATCH 0
42
44#include <cerrno>
45#include <chrono>
46#include <concepts>
47#include <expected>
48#include <format>
49#include <functional>
50#include <future>
51#include <regex>
52#include <string>
53#include <string_view>
54#include <system_error>
55#include <utility>
57
58
59// ///////////////////////// Error Codes, Conditions, and Categories ///////////////////////
60
62namespace error_utils {
63// clang-format off
64// @formatter:off
65
73enum class ExtraError {
74 // Logic errors (std::logic_error exceptions)
78
79 // Runtime errors (std::runtime_error exceptions)
85
86 // Resource and type exceptions
90
91 // Container and value access exceptions
97
98 // Other exceptions
102
104};
105
106
118
119 // clang-format on
120 // @formatter:on
121
123 namespace detail {
124 // Define the error condition category
125 class ExtraErrorConditionCategory final : public std::error_category {
126 public:
127 [[nodiscard]] const char *name() const noexcept override {
128 return "ExtraErrorCondition";
129 }
130
131 [[nodiscard]] std::string message(int ev) const override {
132 switch (static_cast<ExtraErrorCondition>(ev)) {
134 return "Logic error";
136 return "Runtime error";
138 return "Resource error";
140 return "Access error";
142 return "Other error";
143 default:
144 return "Unrecognized error condition";
145 }
146 }
147 };
148
151 inline const std::error_category &extra_error_condition_category() {
152 static ExtraErrorConditionCategory instance;
153 return instance;
154 }
155
159 class ExtraErrorCategory final : public std::error_category {
160 public:
161 [[nodiscard]] const char *name() const noexcept override {
162 return "ExtraError";
163 }
164
165 [[nodiscard]] std::string message(int ev) const override {
166 switch (static_cast<ExtraError>(ev)) {
168 return "Invalid argument exception";
170 return "Length error exception";
172 return "Logic error exception";
173
174 //
176 return "Value too small (underflow exception)";
178 return "Nonexistent local time exception";
180 return "Ambiguous local time exception";
182 return "Format error exception";
184 return "Runtime error exception";
185
186 //
188 return "Bad allocation exception";
190 return "Bad typeid exception";
192 return "Bad cast exception";
193
194 //
196 return "Bad optional access exception";
198 return "Bad expected access exception";
200 return "Bad variant access exception";
202 return "Bad weak pointer exception";
204 return "Bad function call exception";
205
206 //
208 return "Bad exception";
210 return "Exception caught";
212 return "Unknown exception caught";
214 return "Unknown error";
215 default:
216 return "Unrecognized ExtraError";
217 }
218 }
219
223 [[nodiscard]] std::error_condition default_error_condition(int ev) const noexcept override {
224 switch (static_cast<ExtraError>(ev)) {
225 case ExtraError::invalid_argument: [[fallthrough]];
226 case ExtraError::length_error: [[fallthrough]];
228 return {static_cast<int>(ExtraErrorCondition::logic_error), extra_error_condition_category()};
229
230 case ExtraError::value_too_small: [[fallthrough]];
231 case ExtraError::nonexistent_local_time: [[fallthrough]];
232 case ExtraError::ambiguous_local_time: [[fallthrough]];
233 case ExtraError::format_error: [[fallthrough]];
235 return {static_cast<int>(ExtraErrorCondition::runtime_error), extra_error_condition_category()};
236
237 case ExtraError::bad_alloc: [[fallthrough]];
238 case ExtraError::bad_typeid: [[fallthrough]];
240 return {
241 static_cast<int>(ExtraErrorCondition::resource_error), extra_error_condition_category()
242 };
243
244 case ExtraError::bad_optional_access: [[fallthrough]];
245 case ExtraError::bad_expected_access: [[fallthrough]];
246 case ExtraError::bad_variant_access: [[fallthrough]];
247 case ExtraError::bad_weak_ptr: [[fallthrough]];
249 return {static_cast<int>(ExtraErrorCondition::access_error), extra_error_condition_category()};
250
251 case ExtraError::bad_exception: [[fallthrough]];
252 case ExtraError::exception: [[fallthrough]];
253 case ExtraError::unknown_exception: [[fallthrough]];
254 case ExtraError::unknown_error: [[fallthrough]];
255 default:
256 return {static_cast<int>(ExtraErrorCondition::other_error), extra_error_condition_category()};
257 }
258 }
259 };
260
263 inline const std::error_category &extra_error_category() {
264 static ExtraErrorCategory instance;
265 return instance;
266 }
267 } // namespace detail
268
269
272 constexpr std::error_code make_error_code(ExtraError e) {
273 return {static_cast<int>(e), detail::extra_error_category()};
274 }
275
278 constexpr std::error_condition make_error_condition(ExtraErrorCondition e) {
279 return {static_cast<int>(e), detail::extra_error_condition_category()};
280 }
281} // namespace error_utils
282
283
284// STL customization points
285namespace std {
286 template <>
287 struct is_error_code_enum<error_utils::ExtraError> : true_type {};
288
289 template <>
290 struct is_error_condition_enum<error_utils::ExtraErrorCondition> : true_type {};
291} // namespace std
292
295
296
297// ///////////////////////// Error Handling Utilities /////////////////////////
298
299
300namespace error_utils {
301 namespace detail {
303 template <typename>
304 struct is_expected : std::false_type {};
305
307 template <typename T, typename E>
308 struct is_expected<std::expected<T, E>> : std::true_type {};
309
311 template <typename T>
312 inline constexpr bool is_expected_v = is_expected<T>::value;
313
315 template <typename T>
316 concept convertible_to_error_code = (std::is_error_condition_enum_v<T> || std::is_error_code_enum_v<T>) &&
317 requires { { make_error_code(std::declval<T>()) } -> std::same_as<std::error_code>; };
318
320 template <typename T>
321 concept directly_convertible_to_error_condition = requires {
322 { make_error_condition(std::declval<T>()) } -> std::same_as<std::error_condition>;
323 };
324
326 template <typename T>
327 concept comparable_to_error_code = convertible_to_error_code<T> || std::is_same_v<T, std::error_code> ||
328 std::is_same_v<T, std::error_condition> || directly_convertible_to_error_condition<T>;
329 } // namespace detail
330
332 class Error {
333 // clang-format off
334 // @formatter:off
335
336 std::string context_{};
337 std::error_code error_code_{};
338
339 // clang-format on
340 // @formatter:on
341
342 public:
343 constexpr Error() noexcept = default;
344
348 constexpr explicit Error(const std::error_code &code, const std::string_view context = {})
349 : context_{context}, error_code_{code} {}
350
354 constexpr explicit Error(const detail::convertible_to_error_code auto code, const std::string_view context = {})
355 : context_{context}, error_code_{make_error_code(code)} {}
356
357 constexpr Error(const Error &other) noexcept = default;
358
359 constexpr Error(Error &&other) noexcept
360 : context_{std::move(other.context_)},
361 error_code_{other.error_code_} {}
362
363 constexpr Error &operator=(const Error &other) {
364 if (this == &other)
365 return *this;
366 context_ = other.context_;
367 error_code_ = other.error_code_;
368 return *this;
369 }
370
371 constexpr Error &operator=(Error &&other) noexcept {
372 if (this == &other)
373 return *this;
374 context_ = std::move(other.context_);
375 error_code_ = other.error_code_;
376 return *this;
377 }
378
379 ~Error() noexcept = default;
380
381 constexpr friend bool operator==(const Error &lhs, const Error &rhs) noexcept {
382 return lhs.error_code_ == rhs.error_code_;
383 }
384
385 constexpr friend auto operator<=>(const Error &lhs, const Error &rhs) noexcept {
386 return lhs.error_code_ <=> rhs.error_code_;
387 }
388
389 constexpr friend bool operator==(const Error &lhs, const std::error_code &rhs) noexcept {
390 return lhs.error_code_ == rhs;
391 }
392
393 constexpr friend auto operator<=>(const Error &lhs, const std::error_code &rhs) noexcept {
394 return lhs.error_code_ <=> rhs;
395 }
396
397 constexpr friend bool operator==(const Error &lhs, const std::error_condition &rhs) noexcept {
398 return lhs.error_code_ == rhs;
399 }
400
401 constexpr friend std::ostream &operator<<(std::ostream &os, const Error &obj) {
402 return os
403 << obj.message()
404 << "\n(error_code: " << obj.error_code_.value() << " ("
405 << obj.error_code_.category().name() << " category))";
406 }
407
409 [[nodiscard]] constexpr explicit operator bool() const noexcept {
410 return error_code_.operator bool();
411 }
412
414 [[nodiscard]] constexpr const std::error_code &error_code() const noexcept { return error_code_; }
415
417 [[nodiscard]] constexpr const std::string &context() const noexcept { return context_; }
418
420 [[nodiscard]] constexpr int value() const noexcept { return error_code_.value(); }
421
423 [[nodiscard]] constexpr const std::error_category &category() const noexcept {
424 return error_code_.category();
425 }
426
429 [[nodiscard]] constexpr std::string message() const {
430 if (context_.empty()) {
431 return error_code_.message();
432 }
433 return std::format("{}: {}", context_, error_code_.message());
434 }
435
440 template <typename T>
441 requires detail::comparable_to_error_code<T>
442 [[nodiscard]] constexpr bool is(T &&code) const noexcept {
443 if constexpr (std::is_same_v<T, Error> || std::is_same_v<T, std::error_code> ||
444 std::is_same_v<T, std::error_condition>) {
445 // operator== is defined for these types
446 return code == *this;
447 } else if constexpr (detail::convertible_to_error_code<T>) {
448 using std::make_error_code;
449 return error_code_ == make_error_code(std::forward<T>(code));
450 } else if constexpr (detail::directly_convertible_to_error_condition<T>) {
451 using std::make_error_condition;
452 return error_code_ == make_error_condition(std::forward<T>(code));
453 } else static_assert(false, "Should be unreachable.");
454
455 std::unreachable();
456 }
457
464 template <typename Code, typename... Others>
465 requires detail::comparable_to_error_code<Code> && (detail::comparable_to_error_code<Others> && ...)
466 [[nodiscard]] constexpr bool is_any_of(Code &&code, Others &&... others) const noexcept {
467 return is(std::forward<Code>(code)) || (is(std::forward<Others>(others)) || ...);
468 // return (is(std::forward<Code>(code)) || ... || is(std::forward<Others>(others)));
469 }
470
472 constexpr friend void swap(Error &lhs, Error &rhs) noexcept {
473 using std::swap;
474 swap(lhs.context_, rhs.context_);
475 swap(lhs.error_code_, rhs.error_code_);
476 }
477 };
478
479
482 template <typename T = void>
483 using Result = std::expected<T, Error>;
484
485 // clang-format off
486 // @formatter:off
487
488 // Common result type aliases
493
494 // clang-format on
495 // @formatter:on
496
504 template <typename T, typename E, typename Ctx = std::string_view>
505 requires detail::convertible_to_error_code<E>
506 [[nodiscard]] constexpr Result<T> make_error(E &&code, Ctx &&context = {}) {
507 return std::unexpected(Error{std::forward<E>(code), std::forward<Ctx>(context)});
508 }
509
515 template <typename T>
516 [[nodiscard]] constexpr Result<T> make_error(const std::error_code &code, const std::string_view context = {}) {
517 return std::unexpected(Error{code, context});
518 }
519
525 template <typename T>
526 [[nodiscard]] constexpr Result<T> make_error(const std::regex_constants::error_type code,
527 std::string_view context = {}) {
528 auto create_unexpected = [&context]<typename C>(C &&err_code, const std::string_view msg) {
529 // Ignore the additional message if the error came from an exception.
530 // The exception message is already included in the context.
531 if (context.ends_with("\x02")) {
532 context.remove_suffix(1);
533 return std::unexpected(Error{std::forward<C>(err_code), context});
534 }
535
536 return std::unexpected(Error{
537 std::forward<C>(err_code), context.empty() ? msg : std::format("{}: {}", context, msg)
538 });
539 };
540
541 // Map regex error codes to std::error_code
542 switch (code) {
543 case std::regex_constants::error_collate:
544 return create_unexpected(std::errc::invalid_argument,
545 "Regex error: invalid collating element name");
546
547 case std::regex_constants::error_ctype:
548 return create_unexpected(std::errc::invalid_argument,
549 "Regex error: invalid character class name");
550
551 case std::regex_constants::error_escape:
552 return create_unexpected(std::errc::invalid_argument,
553 "Regex error: invalid escaped character or a trailing escape");
554
555 case std::regex_constants::error_backref:
556 return create_unexpected(std::errc::invalid_argument,
557 "Regex error: invalid back reference");
558
559 case std::regex_constants::error_brack:
560 return create_unexpected(std::errc::invalid_argument,
561 "Regex error: mismatched square brackets ('[' and ']')");
562
563 case std::regex_constants::error_paren:
564 return create_unexpected(std::errc::invalid_argument,
565 "Regex error: mismatched parentheses ('(' and ')')");
566
567 case std::regex_constants::error_brace:
568 return create_unexpected(std::errc::invalid_argument,
569 "Regex error: mismatched curly braces ('{' and '}')");
570
571 case std::regex_constants::error_badbrace:
572 return create_unexpected(std::errc::invalid_argument,
573 "Regex error: invalid range in a {} expression");
574
575 case std::regex_constants::error_range:
576 return create_unexpected(std::errc::invalid_argument,
577 "Regex error: invalid character range");
578
579 case std::regex_constants::error_space:
580 return create_unexpected(std::errc::not_enough_memory,
581 "Regex error: insufficient memory to convert the expression"
582 " into a finite state machine");
583
584 case std::regex_constants::error_badrepeat:
585 return create_unexpected(std::errc::invalid_argument,
586 "Regex error: '*', '?', '+' or '{' was not preceded"
587 " by a valid regular expression");
588
589 case std::regex_constants::error_complexity:
590 return create_unexpected(std::errc::result_out_of_range,
591 "Regex error: the complexity of an attempted match"
592 " exceeded a predefined level");
593
594 case std::regex_constants::error_stack:
595 return create_unexpected(std::errc::not_enough_memory,
596 "Regex error: insufficient memory to perform a match");
597
598 default:
599 return create_unexpected(ExtraError::unknown_error, "Regex error: unknown error");
600 }
601 }
602
605 [[nodiscard]] inline std::error_code last_error() noexcept {
606 int err = errno;
607 errno = 0; // Reset errno to avoid side effects
608 return std::make_error_code(static_cast<std::errc>(err));
609 }
610
615 template <typename T>
616 [[nodiscard]] Result<T> make_error_from_errno(const std::string_view context = {}) {
617 return make_error<T>(last_error(), context);
618 }
619
629 template <typename Func, typename R = std::invoke_result_t<Func>>
630 [[nodiscard]] auto with_errno(Func &&func, const std::string_view error_context = {}) -> Result<R> {
631 // Reset errno before calling the function to avoid side effects
632 errno = 0;
633
634 if constexpr (std::is_void_v<R>) {
635 std::forward<Func>(func)();
636 if (errno != 0) {
637 return make_error_from_errno<void>(error_context);
638 }
639 return {};
640 } else {
641 R result = std::forward<Func>(func)();
642 if (errno != 0) {
643 return make_error_from_errno<R>(error_context);
644 }
645 return result;
646 }
647 }
648
664 template <typename Func>
665 requires std::is_nothrow_invocable_v<Func>
666 [[nodiscard]] IntResult invoke_with_syscall_api(Func &&func, const std::string_view error_context = {}) noexcept {
667 using R = std::invoke_result_t<Func>;
668 static_assert(std::is_integral_v<R> && std::convertible_to<R, int>,
669 "func must return an integral type convertible to int");
670
671 // Reset errno before calling the function to avoid side effects
672 errno = 0;
673
674 R result = std::forward<Func>(func)();
675 if (result == -1) {
676 return make_error_from_errno<int>(error_context);
677 }
678
679 return result;
680 }
681
688 template <typename Func, typename R = std::invoke_result_t<Func>>
689 [[nodiscard]] constexpr auto try_catch(Func &&func, std::string_view context = {}) -> Result<R> {
690 auto create_error = [&context]<typename T>(T &&code, const std::string_view default_msg) -> Result<R> {
691 return make_error<R>(std::forward<T>(code),
692 context.empty() ? default_msg : std::format("{}: {}", context, default_msg));
693 };
694
695 try {
696 return std::forward<Func>(func)();
697
698 // Logic errors
699 } catch (const std::invalid_argument &e) {
700 return create_error(ExtraError::invalid_argument, e.what());
701 } catch (const std::domain_error &e) {
702 return create_error(std::errc::argument_out_of_domain, e.what());
703 } catch (const std::length_error &e) {
704 return create_error(ExtraError::length_error, e.what());
705 } catch (const std::out_of_range &e) {
706 return create_error(std::errc::result_out_of_range, e.what());
707 } catch (const std::future_error &e) {
708 return create_error(e.code(), e.what());
709 } catch (const std::logic_error &e) {
710 return create_error(ExtraError::logic_error, e.what());
711
712 // Runtime errors
713 } catch (const std::range_error &e) {
714 return create_error(std::errc::result_out_of_range, e.what());
715 } catch (const std::overflow_error &e) {
716 return create_error(std::errc::value_too_large, e.what());
717 } catch (const std::underflow_error &e) {
718 return create_error(ExtraError::value_too_small, e.what());
719 } catch (const std::regex_error &e) {
720 return create_error(e.code(), std::format("{}\x02", e.what()));
721 } catch (const std::system_error &e) {
722 return create_error(e.code(), ""); // e.what() will be deduced from the code
723 } catch (const std::chrono::nonexistent_local_time &e) {
724 return create_error(ExtraError::nonexistent_local_time, e.what());
725 } catch (const std::chrono::ambiguous_local_time &e) {
726 return create_error(ExtraError::ambiguous_local_time, e.what());
727 } catch (const std::format_error &e) {
728 return create_error(ExtraError::format_error, e.what());
729 } catch (const std::runtime_error &e) {
730 return create_error(ExtraError::runtime_error, e.what());
731
732 // Resource and type errors
733 } catch (const std::bad_alloc &e) {
734 return create_error(ExtraError::bad_alloc, e.what());
735 } catch (const std::bad_typeid &e) {
736 return create_error(ExtraError::bad_typeid, e.what());
737 } catch (const std::bad_cast &e) {
738 return create_error(ExtraError::bad_cast, e.what());
739
740 // Container and value access errors
741 } catch (const std::bad_optional_access &e) {
742 return create_error(ExtraError::bad_optional_access, e.what());
743 } catch (const std::bad_expected_access<void> &e) {
744 return create_error(ExtraError::bad_expected_access, e.what());
745 } catch (const std::bad_variant_access &e) {
746 return create_error(ExtraError::bad_variant_access, e.what());
747 } catch (const std::bad_weak_ptr &e) {
748 return create_error(ExtraError::bad_weak_ptr, e.what());
749 } catch (const std::bad_function_call &e) {
750 return create_error(ExtraError::bad_function_call, e.what());
751 } catch (const std::bad_exception &e) {
752 return create_error(ExtraError::bad_exception, e.what());
753
754 // Catch-all for any other exceptions
755 } catch (const std::exception &e) {
756 return create_error(ExtraError::exception, e.what());
757 } catch (...) {
758 return create_error(ExtraError::unknown_exception, "Unknown exception");
759 }
760 }
761
766 template <typename T>
767 [[nodiscard]] constexpr Result<T> first_of(std::initializer_list<Result<T>> results) {
768 if (results.size() == 0) {
769 return make_error<T>(std::errc::invalid_argument, "No alternatives provided");
770 }
771 std::string combined_errors{};
772
773 for (const auto &result : results) {
774 if (result) {
775 return result;
776 }
777 if (!combined_errors.empty()) {
778 combined_errors += "; ";
779 }
780 combined_errors += result.error().message();
781 }
782
783 return make_error<T>(ExtraError::unknown_error, combined_errors);
784 }
785} // namespace error_utils
786
787namespace std {
788 template <>
789 struct formatter<error_utils::Error> {
790 static constexpr auto parse(format_parse_context &ctx) {
791 return ctx.begin();
792 }
793
794 static auto format(const error_utils::Error &error, format_context &ctx) {
795 return format_to(ctx.out(), "{} \n(error_code: {}, category: {})",
796 error.message(), error.value(), error.category().name());
797 }
798 };
799
800 template <>
801 struct hash<error_utils::Error> {
802 size_t operator()(const error_utils::Error &error) const noexcept {
803 return hash<error_code>{}(error.error_code());
804 }
805 };
806}
807
808
809// ///////////////////////// Common Result Type Aliases /////////////////////////
810
A wrapper class for system error codes with additional context.
Definition error_utils.hpp:332
constexpr Error(const detail::convertible_to_error_code auto code, const std::string_view context={})
Create an error with a type convertible to std::error_code and optional context.
Definition error_utils.hpp:354
constexpr Error(const Error &other) noexcept=default
constexpr friend void swap(Error &lhs, Error &rhs) noexcept
Swap the contents of two Error objects.
Definition error_utils.hpp:472
constexpr friend bool operator==(const Error &lhs, const std::error_code &rhs) noexcept
Definition error_utils.hpp:389
constexpr friend auto operator<=>(const Error &lhs, const std::error_code &rhs) noexcept
Definition error_utils.hpp:393
constexpr bool is(T &&code) const noexcept
Check if the error is of a specific type.
Definition error_utils.hpp:442
constexpr Error & operator=(const Error &other)
Definition error_utils.hpp:363
constexpr int value() const noexcept
Returns the value of the error code.
Definition error_utils.hpp:420
constexpr Error & operator=(Error &&other) noexcept
Definition error_utils.hpp:371
constexpr std::string message() const
Get the error message including context if available.
Definition error_utils.hpp:429
constexpr Error(Error &&other) noexcept
Definition error_utils.hpp:359
constexpr const std::error_code & error_code() const noexcept
Returns a constant reference to the underlying error code.
Definition error_utils.hpp:414
constexpr const std::string & context() const noexcept
Returns a constant reference to the context string.
Definition error_utils.hpp:417
constexpr bool is_any_of(Code &&code, Others &&... others) const noexcept
Check if the error belongs to any of the specified error codes or error conditions.
Definition error_utils.hpp:466
constexpr friend std::ostream & operator<<(std::ostream &os, const Error &obj)
Definition error_utils.hpp:401
constexpr const std::error_category & category() const noexcept
Returns the category of the error code.
Definition error_utils.hpp:423
constexpr friend auto operator<=>(const Error &lhs, const Error &rhs) noexcept
Definition error_utils.hpp:385
constexpr friend bool operator==(const Error &lhs, const std::error_condition &rhs) noexcept
Definition error_utils.hpp:397
constexpr Error() noexcept=default
~Error() noexcept=default
Contains utilities for error handling and classification.
Definition error_utils.hpp:62
ExtraError
Represents specific error codes for exception handling and error classification.
Definition error_utils.hpp:73
@ format_error
std::format_error exception.
Definition error_utils.hpp:83
@ bad_alloc
std::bad_alloc exception.
Definition error_utils.hpp:87
@ bad_weak_ptr
std::bad_weak_ptr exception.
Definition error_utils.hpp:95
@ unknown_exception
catch-all for any other exceptions.
Definition error_utils.hpp:101
@ exception
all std::exception exceptions.
Definition error_utils.hpp:100
@ value_too_small
std::underflow_error exception.
Definition error_utils.hpp:80
@ bad_exception
std::bad_exception exception.
Definition error_utils.hpp:99
@ unknown_error
Unknown error (not related to exceptions).
Definition error_utils.hpp:103
@ runtime_error
std::runtime_error base exception.
Definition error_utils.hpp:84
@ nonexistent_local_time
std::chrono::nonexistent_local_time exception.
Definition error_utils.hpp:81
@ length_error
std::length_error exception.
Definition error_utils.hpp:76
@ bad_typeid
std::bad_typeid exception.
Definition error_utils.hpp:88
@ logic_error
std::logic_error base exception.
Definition error_utils.hpp:77
@ bad_optional_access
std::bad_optional_access exception.
Definition error_utils.hpp:92
@ bad_expected_access
std::bad_expected_access exception.
Definition error_utils.hpp:93
@ ambiguous_local_time
std::chrono::ambiguous_local_time exception.
Definition error_utils.hpp:82
@ invalid_argument
std::invalid_argument exception.
Definition error_utils.hpp:75
@ bad_cast
std::bad_cast exception.
Definition error_utils.hpp:89
@ bad_function_call
std::bad_function_call exception.
Definition error_utils.hpp:96
@ bad_variant_access
std::bad_variant_access exception.
Definition error_utils.hpp:94
Result<> VoidResult
Result type for void (std::expected<void, Error>)
Definition error_utils.hpp:489
ExtraErrorCondition
Represents categories of error conditions for error handling and classification.
Definition error_utils.hpp:111
@ resource_error
Errors related to resource allocation and management.
Definition error_utils.hpp:114
@ access_error
Errors related to invalid access of data structures.
Definition error_utils.hpp:115
@ runtime_error
Errors occurring during program execution.
Definition error_utils.hpp:113
@ logic_error
Errors related to program logic and invalid operations.
Definition error_utils.hpp:112
@ other_error
Other errors that do not fit into the above categories.
Definition error_utils.hpp:116
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
Result< T > make_error_from_errno(const std::string_view context={})
Create an error result from the current errno value.
Definition error_utils.hpp:616
Result< bool > BoolResult
Result type for booleans (std::expected<bool, Error>)
Definition error_utils.hpp:492
constexpr Result< T > make_error(E &&code, Ctx &&context={})
Create an error result of the specified type.
Definition error_utils.hpp:506
Result< std::string > StringResult
Result type for strings (std::expected<std::string, Error>)
Definition error_utils.hpp:490
constexpr Result< T > first_of(std::initializer_list< Result< T > > results)
Return first success result from multiple alternatives.
Definition error_utils.hpp:767
std::expected< T, Error > Result
A specialization of std::expected for the Error type.
Definition error_utils.hpp:483
constexpr std::error_condition make_error_condition(ExtraErrorCondition e)
Create an error condition from an ExtraErrorCondition enum value.
Definition error_utils.hpp:278
auto with_errno(Func &&func, const std::string_view error_context={}) -> Result< R >
Execute a function that may set errno, capturing the result and any error.
Definition error_utils.hpp:630
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
std::error_code last_error() noexcept
Retrieve the last system error code and reset errno.
Definition error_utils.hpp:605
constexpr std::error_code make_error_code(ExtraError e)
Create an error code from an ExtraError enum value.
Definition error_utils.hpp:272