Skip to content

feat: Replace outcome with Boost's version of outcome to remove dependence on quickcpplib. #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ if(BUILD_TESTING AND YSTDLIB_CPP_BUILD_TESTING)
set(YSTDLIB_CPP_ENABLE_TESTS ON)
endif()

find_package(outcome REQUIRED)
if(outcome_FOUND)
message(STATUS "Found outcome.")
find_package(Boost REQUIRED)
if(Boost_FOUND)
message(STATUS "Found Boost ${Boost_VERSION}.")
else()
message(FATAL_ERROR "Could not find libraries for outcome.")
message(STATUS "Could not find libraries for Boost.")
endif()

if(YSTDLIB_CPP_ENABLE_TESTS)
Expand Down
4 changes: 2 additions & 2 deletions lint-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Lock to v19.x until we can upgrade our code to fix new v20 issues.
clang-format~=19.1
clang-format>=20.1.0
# Lock to v19.x until we can upgrade our code to fix new v20 issues.
clang-tidy~=19.1
clang-tidy>=19.1.0
colorama>=0.4.6
gersemi>=0.16.2
yamllint>=1.35.1
2 changes: 1 addition & 1 deletion src/ystdlib/error_handling/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ cpp_library(
Result.hpp
utils.hpp
PUBLIC_LINK_LIBRARIES
outcome::hl
Boost::headers
TESTS_SOURCES
test/constants.hpp
test/test_ErrorCode.cpp
Expand Down
2 changes: 1 addition & 1 deletion src/ystdlib/error_handling/ErrorCode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class ErrorCode {
/**
* @return The reference to the singleton of the corresponded error category.
*/
[[nodiscard]] constexpr static auto get_category() -> ErrorCategory<ErrorCodeEnum> const& {
[[nodiscard]] static constexpr auto get_category() -> ErrorCategory<ErrorCodeEnum> const& {
return cCategory;
}

Expand Down
36 changes: 9 additions & 27 deletions src/ystdlib/error_handling/Result.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#ifndef YSTDLIB_ERROR_HANDLING_RESULT_HPP
#define YSTDLIB_ERROR_HANDLING_RESULT_HPP

#include <boost/outcome/config.hpp>
#include <boost/outcome/std_result.hpp>
#include <boost/outcome/success_failure.hpp>
#include <boost/outcome/try.hpp>
#include <system_error>

#include <outcome/config.hpp>
#include <outcome/std_result.hpp>
#include <outcome/success_failure.hpp>
#include <outcome/try.hpp>

namespace ystdlib::error_handling {
/**
* A Rust-style `Result<T, E>` type for standardized, exception-free error handling.
Expand All @@ -20,34 +19,16 @@ namespace ystdlib::error_handling {
* @tparam ErrorType The type used to represent errors.
*/
template <typename ReturnType, typename ErrorType = std::error_code>
using Result = OUTCOME_V2_NAMESPACE::std_result<ReturnType, ErrorType>;
using Result = BOOST_OUTCOME_V2_NAMESPACE::std_result<ReturnType, ErrorType>;

/**
* @return A value indicating successful completion of a function that returns a void result (i.e.,
* `Result<void, E>`).
*/
[[nodiscard]] inline auto success() -> OUTCOME_V2_NAMESPACE::success_type<void> {
return OUTCOME_V2_NAMESPACE::success();
[[nodiscard]] inline auto success() -> BOOST_OUTCOME_V2_NAMESPACE::success_type<void> {
return BOOST_OUTCOME_V2_NAMESPACE::success();
}

/**
* A function-style macro that emulates Rust’s try (`?`) operator for error propagation.
*
* @param expr An expression that evaluates to a `Result` object.
*
* Behavior:
* - If `expr` represents an error (i.e., `expr.has_error()` returns true), the macro performs an
* early return from the enclosing function with the contained error.
* - Otherwise, it unwraps and yields the successful value as an rvalue reference (`expr.value()`).
*
* NOTE: This macro is only supported on GCC and Clang due to reliance on compiler-specific
* extensions.
*/
#ifdef OUTCOME_TRYX
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define YSTDLIB_ERROR_HANDLING_TRYX(expr) OUTCOME_TRYX(expr)
#endif

/**
* A function-style macro for propagating errors from expressions that evaluate to a void result
* (`Result<void, E>`).
Expand All @@ -60,7 +41,8 @@ using Result = OUTCOME_V2_NAMESPACE::std_result<ReturnType, ErrorType>;
* - Otherwise, execution continues normally.
*/
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define YSTDLIB_ERROR_HANDLING_TRYV(expr) OUTCOME_TRYV(expr)
#define YSTDLIB_ERROR_HANDLING_TRYV(expr) BOOST_OUTCOME_TRYV(expr)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Guard TRYV macro definition.

Wrap YSTDLIB_ERROR_HANDLING_TRYV with #ifdef BOOST_OUTCOME_TRYV to prevent compilation errors if the underlying macro is unavailable:

-// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
-#define YSTDLIB_ERROR_HANDLING_TRYV(expr) BOOST_OUTCOME_TRYV(expr)
+#ifdef BOOST_OUTCOME_TRYV
+  // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
+  #define YSTDLIB_ERROR_HANDLING_TRYV(expr) BOOST_OUTCOME_TRYV(expr)
+#endif
🤖 Prompt for AI Agents
In src/ystdlib/error_handling/Result.hpp at line 63, the macro
YSTDLIB_ERROR_HANDLING_TRYV is defined directly as BOOST_OUTCOME_TRYV without
checking if BOOST_OUTCOME_TRYV is defined. To fix this, wrap the macro
definition inside an #ifdef BOOST_OUTCOME_TRYV preprocessor check to ensure it
is only defined if BOOST_OUTCOME_TRYV exists, preventing compilation errors when
the underlying macro is unavailable.

#define YSTDLIB_ERROR_HANDLING_TRY(val, expr) BOOST_OUTCOME_TRY(auto&& val, expr)
} // namespace ystdlib::error_handling

#endif // YSTDLIB_ERROR_HANDLING_RESULT_HPP
10 changes: 6 additions & 4 deletions src/ystdlib/error_handling/test/test_Result.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ TEST_CASE("test_result_int_in_main", "[error_handling][Result]") {

TEST_CASE("test_result_int_propagate", "[error_handling][Result]") {
auto main_func = [&](bool is_error) -> Result<int> {
return YSTDLIB_ERROR_HANDLING_TRYX(cIntFunc(is_error));
YSTDLIB_ERROR_HANDLING_TRY(value, cIntFunc(is_error));
return value;
};
auto const main_no_error{main_func(false)};
REQUIRE_FALSE(main_no_error.has_error());
Expand All @@ -106,8 +107,8 @@ TEST_CASE("test_result_unique_ptr", "[error_handling][Result]") {

auto const result_has_error{cUniquePtrFunc(true)};
REQUIRE(result_has_error.has_error());
REQUIRE(AlwaysSuccessErrorCode{AlwaysSuccessErrorCodeEnum::Success} == result_has_error.error()
);
REQUIRE(AlwaysSuccessErrorCode{AlwaysSuccessErrorCodeEnum::Success}
== result_has_error.error());
}

TEST_CASE("test_result_unique_ptr_in_main", "[error_handling][Result]") {
Expand All @@ -126,7 +127,8 @@ TEST_CASE("test_result_unique_ptr_in_main", "[error_handling][Result]") {

TEST_CASE("test_result_unique_ptr_propagate", "[error_handling][Result]") {
auto main_func = [&](bool is_error) -> Result<std::unique_ptr<int>> {
return YSTDLIB_ERROR_HANDLING_TRYX(cUniquePtrFunc(is_error));
YSTDLIB_ERROR_HANDLING_TRY(value, cUniquePtrFunc(is_error));
return value;
};
auto const main_no_error{main_func(false)};
REQUIRE_FALSE(main_no_error.has_error());
Expand Down
4 changes: 4 additions & 0 deletions src/ystdlib/wrapped_facade_headers/test/test_sys_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <catch2/catch_test_macros.hpp>

namespace ystdlib::wrapped_facade_headers::test {

namespace {
TEST_CASE("test_sys_types_u_char", "[wrapped_facade_headers][sys_types][u_char]") {
u_char const i{0};
REQUIRE(0 == i);
Expand Down Expand Up @@ -163,4 +165,6 @@ TEST_CASE("test_sys_types_fsfilcnt_t", "[wrapped_facade_headers][sys_types][fsfi
fsfilcnt_t const i{0};
REQUIRE(0 == i);
}
}

} // namespace ystdlib::wrapped_facade_headers::test
2 changes: 1 addition & 1 deletion taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ includes:
build: "./taskfiles/build.yaml"
deps: "./taskfiles/deps.yaml"
lint: "./taskfiles/lint.yaml"
utils: "tools/yscope-dev-utils/taskfiles/utils.yaml"
utils: "tools/yscope-dev-utils/exports/taskfiles/utils/utils.yaml"

vars:
G_BUILD_DIR: "{{.ROOT_DIR}}/build"
Expand Down
8 changes: 4 additions & 4 deletions taskfiles/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ tasks:
deps:
- "init"
cmds:
- task: ":utils:cmake-build"
- task: ":utils:cmake:build"
vars:
BUILD_DIR: "{{.G_BUILD_DIR}}"

Expand All @@ -21,7 +21,7 @@ tasks:
deps:
- "init"
cmds:
- task: ":utils:cmake-build"
- task: ":utils:cmake:build"
vars:
BUILD_DIR: "{{.G_BUILD_DIR}}"
TARGETS:
Expand Down Expand Up @@ -49,7 +49,7 @@ tasks:
clean:
desc: "Removes all built artifacts."
deps:
- task: ":utils:cmake-clean"
- task: ":utils:cmake:clean"
vars:
BUILD_DIR: "{{.G_BUILD_DIR}}"

Expand All @@ -59,7 +59,7 @@ tasks:
- ":deps:install-all"
run: "once"
cmds:
- task: ":utils:cmake-generate"
- task: ":utils:cmake:generate"
vars:
BUILD_DIR: "{{.G_BUILD_DIR}}"
SOURCE_DIR: "{{.ROOT_DIR}}"
Loading
Loading