From ced3b95c5583ac6c67ffd91b68c6e2a7e7215042 Mon Sep 17 00:00:00 2001 From: DNKpp Date: Sat, 23 May 2026 23:42:56 +0200 Subject: [PATCH 1/3] deps: upgrade catch2 to v3.15.0 --- cmake/Findgimo-catch2.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/Findgimo-catch2.cmake b/cmake/Findgimo-catch2.cmake index fe9d7e4..157680a 100644 --- a/cmake/Findgimo-catch2.cmake +++ b/cmake/Findgimo-catch2.cmake @@ -1,4 +1,4 @@ -# Copyright Dominic (DNKpp) Koepke 2025 - 2026. +# Copyright Dominic (DNKpp) Koepke 2025-2026. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # https://www.boost.org/LICENSE_1_0.txt) @@ -8,7 +8,7 @@ include(Gimo-get_cpm) # fixes reporting in clion set(CATCH_CONFIG_CONSOLE_WIDTH 800 CACHE STRING "") -CPMAddPackage("gh:catchorg/Catch2@3.13.0") +CPMAddPackage("gh:catchorg/Catch2@3.15.0") if (Catch2_ADDED) include("${Catch2_SOURCE_DIR}/extras/Catch.cmake") From a18791771112e3a831ac977075f25ad2453483e7 Mon Sep 17 00:00:00 2001 From: DNKpp Date: Sun, 24 May 2026 00:02:37 +0200 Subject: [PATCH 2/3] feat: or_else algorithm accepts actions returning void. --- include/gimo/algorithm/OrElse.hpp | 41 ++++++++++++++----- .../or_else/action-return-mismatch.cpp | 4 +- test/unit-tests/algorithm/OrElse.cpp | 21 +++++++++- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/include/gimo/algorithm/OrElse.hpp b/include/gimo/algorithm/OrElse.hpp index c0900f6..e72f0a2 100644 --- a/include/gimo/algorithm/OrElse.hpp +++ b/include/gimo/algorithm/OrElse.hpp @@ -1,4 +1,4 @@ -// Copyright Dominic (DNKpp) Koepke 2025. +// Copyright Dominic (DNKpp) Koepke 2025-2026. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // https://www.boost.org/LICENSE_1_0.txt) @@ -21,18 +21,18 @@ namespace gimo::detail::or_else { template - consteval Nullable* print_diagnostics() + consteval Nullable& print_diagnostics() { if constexpr (!std::is_invocable_v) { static_assert(always_false_v, "The or_else algorithm requires an action invocable without any arguments."); } - else if constexpr (!std::same_as>) + else if constexpr (!std::same_as> && !std::is_void_v>) { - static_assert(always_false_v, "The or_else algorithm requires an action returning the same nullable type."); + static_assert(always_false_v, "The or_else algorithm requires an action returning the same nullable type or void."); } - return nullptr; + return std::declval(); } template @@ -59,7 +59,15 @@ namespace gimo::detail::or_else [[nodiscard]] constexpr std::remove_cvref_t on_null(Action&& action, [[maybe_unused]] Nullable&& opt) { - return std::invoke(std::forward(action)); + if constexpr (std::is_void_v>) + { + std::invoke(std::forward(action)); + return null_v; + } + else + { + return std::invoke(std::forward(action)); + } } template @@ -72,13 +80,24 @@ namespace gimo::detail::or_else std::forward(steps)...); } + template + requires std::is_void_v> + [[nodiscard]] + constexpr auto on_null(Action&& action, Nullable&& opt, Next&& next, Steps&&... steps) + { + return std::forward(next).on_null( + or_else::on_null(std::forward(action), std::forward(opt)), + std::forward(steps)...); + } + struct traits { template static constexpr bool is_applicable_on = requires { requires std::same_as< - std::remove_cvref_t, - std::remove_cvref_t>>; + std::remove_cvref_t, + std::remove_cvref_t>> + || std::is_void_v>; }; template @@ -94,7 +113,7 @@ namespace gimo::detail::or_else } else { - return *or_else::print_diagnostics(); + return or_else::print_diagnostics(); } } @@ -111,7 +130,7 @@ namespace gimo::detail::or_else } else { - return *or_else::print_diagnostics(); + return or_else::print_diagnostics(); } } }; @@ -133,7 +152,7 @@ namespace gimo * \return A Pipeline step containing the `or_else` algorithm. * \details * - **On Value**: Propagates the value state immediately (i.e., `action` is not executed). - * - **On Null**: Invokes the `action`. The `action` **must** return a `nullable` type. + * - **On Null**: Invokes the `action`. The `action` must either return the **exact same** `nullable` type or `void`. * \see https://en.wikipedia.org/wiki/Monad_(functional_programming) */ template diff --git a/test/compile-errors/or_else/action-return-mismatch.cpp b/test/compile-errors/or_else/action-return-mismatch.cpp index 5eab65f..86f1d56 100644 --- a/test/compile-errors/or_else/action-return-mismatch.cpp +++ b/test/compile-errors/or_else/action-return-mismatch.cpp @@ -1,4 +1,4 @@ -// Copyright Dominic (DNKpp) Koepke 2025. +// Copyright Dominic (DNKpp) Koepke 2025-2026. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // https://www.boost.org/LICENSE_1_0.txt) @@ -8,7 +8,7 @@ /* -The or_else algorithm requires an action returning the same nullable type\. +The or_else algorithm requires an action returning the same nullable type or void\. */ diff --git a/test/unit-tests/algorithm/OrElse.cpp b/test/unit-tests/algorithm/OrElse.cpp index 9104e34..3bac267 100644 --- a/test/unit-tests/algorithm/OrElse.cpp +++ b/test/unit-tests/algorithm/OrElse.cpp @@ -1,4 +1,4 @@ -// Copyright Dominic (DNKpp) Koepke 2025. +// Copyright Dominic (DNKpp) Koepke 2025-2026. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // https://www.boost.org/LICENSE_1_0.txt) @@ -180,3 +180,22 @@ TEMPLATE_LIST_TEST_CASE( and finally::returns(1337); CHECK(1337 == pipeline.apply(std::optional{})); } + +TEST_CASE( + "gimo::or_else accepts actions returning void.", + "[algorithm]") +{ + mimicpp::Mock action{}; + auto const pipeline = or_else(std::ref(action)); + + SECTION("When a value is contained, the action is not invoked.") + { + CHECK(1337 == pipeline.apply(std::optional{1337})); + } + + SECTION("When no value is contained, the action is invoked and null is returned.") + { + SCOPED_EXP action.expect_call(); + CHECK(!pipeline.apply(std::optional{})); + } +} From f5948ef964de1be4438ae2fc683dcfb2160d2718 Mon Sep 17 00:00:00 2001 From: DNKpp Date: Sun, 24 May 2026 00:07:51 +0200 Subject: [PATCH 3/3] refactor: replace several [[maybe_unused]] with explicit out-commented parameters --- include/gimo/algorithm/OrElse.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/gimo/algorithm/OrElse.hpp b/include/gimo/algorithm/OrElse.hpp index e72f0a2..c96595b 100644 --- a/include/gimo/algorithm/OrElse.hpp +++ b/include/gimo/algorithm/OrElse.hpp @@ -37,7 +37,7 @@ namespace gimo::detail::or_else template [[nodiscard]] - constexpr std::remove_cvref_t on_value([[maybe_unused]] Action&& action, Nullable&& opt) + constexpr std::remove_cvref_t on_value(Action&& /*action*/, Nullable&& opt) { return std::forward(opt); } @@ -45,7 +45,7 @@ namespace gimo::detail::or_else template [[nodiscard]] constexpr auto on_value( - [[maybe_unused]] Action&& action, + Action&& /*action*/, Nullable&& opt, Next&& next, Steps&&... steps) @@ -57,7 +57,7 @@ namespace gimo::detail::or_else template [[nodiscard]] - constexpr std::remove_cvref_t on_null(Action&& action, [[maybe_unused]] Nullable&& opt) + constexpr std::remove_cvref_t on_null(Action&& action, Nullable&& /*opt*/) { if constexpr (std::is_void_v>) {