From e33c6154a019fa7f4eaebcb7b6056a376e5f121a Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Thu, 26 Mar 2026 22:58:15 +0800 Subject: [PATCH 1/7] refactor: Update implementation plan with clear responsibilities and dependencies for algorithms and conversion layers Signed-off-by: FrozenlemonTee <1115306170@qq.com> --- .agents/docs/plans/implementation-plan.md | 42 +++++++++++++++++------ 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/.agents/docs/plans/implementation-plan.md b/.agents/docs/plans/implementation-plan.md index 55ea982..15fcded 100644 --- a/.agents/docs/plans/implementation-plan.md +++ b/.agents/docs/plans/implementation-plan.md @@ -1,10 +1,12 @@ -# Primitives 下一步实现计划清单(2026-03-23) +# Primitives 下一步实现计划清单(2026-03-26) ## 总体原则 - [ ] 先定义稳定 API 边界,再落地实现 - [ ] 每个能力都配套 tests + examples + docs - [ ] 高风险转换默认禁止隐式触发,只允许显式 API +- [ ] 明确分层职责:`algorithms` 负责值域/排序/边界元信息与值算法;`conversion` 负责显式类型变换 +- [ ] 明确依赖方向:`conversion` 可依赖 `algorithms`,`algorithms` 不反向依赖 `conversion` ## M1. C API 互操作层(双向) @@ -27,21 +29,30 @@ ### 工作清单 - [ ] 扩展 concept 分层(category/representation/policy-capability) -- [ ] 完善 `traits` 元信息(`kind`、`rep_type`、limits、policy tags) -- [ ] 提供检测类 API(可转换性/是否有损/错误模型能力) +- [ ] 明确 `underlying::traits` 与 `algorithms::traits` 的职责边界:前者描述表示层;后者描述值算法层 +- [ ] 完善 `traits` 元信息(`kind`、`rep_type`、policy tags) +- [ ] 设计 `algorithms::traits`,内容参考 `std::numeric_limits`,但只保留算法/比较所需子集: +- [ ] `min()` / `lowest()` / `max()` / `epsilon()` / `infinity()` / `quiet_nan()` +- [ ] `is_bounded` / `is_exact` / `is_signed` / `is_integer` / `is_iec559` +- [ ] `has_infinity` / `has_quiet_nan` / `digits` / `digits10` / `radix` +- [ ] 增加排序能力元信息:`comparison_category`、`totally_ordered`、`partially_ordered`、`unordered_possible` +- [ ] 提供双参聚合元信息:`algorithms::common_traits`,统一暴露 `common_rep`、可比较性、边界查询与策略兼容性 +- [ ] 提供检测类 API(可比较性/可裁剪性/可转换性/是否有损/错误模型能力) - [ ] 统一 `constexpr` 查询入口,减少分散 traits 访问 - [ ] 增加编译期测试矩阵(`static_assert` 覆盖) ### 验收标准 - [ ] 上层模块仅依赖公开 concept/traits,不依赖 `details::*` -- [ ] 元信息可支撑转换层与算法层的约束判定 +- [ ] `algorithms::traits` 可直接支撑算法层判定,并作为 conversion 的元信息依赖 +- [ ] `std::numeric_limits` 相关逻辑不再散落在 `conversion`/`operations` 内部 ## M3. 显式转换层(任意策略组适用) ### 工作清单 - [ ] 设计统一接口族(建议):`explicit_cast`、`try_cast`、`checked_cast` +- [ ] 将边界、NaN、无穷大、精度与排序相关判定统一改为依赖 `algorithms::traits` / `algorithms::common_traits` - [ ] 支持任意策略组组合,不绑定特定策略实现 - [ ] 风险可见化(截断/溢出/精度损失)并可程序化读取 - [ ] 定义失败语义(错误码或 expected 风格,按策略可配置) @@ -51,28 +62,37 @@ - [ ] 所有跨类高风险转换必须走显式 API - [ ] 风险信息可在编译期或运行期被确定性获取 +- [ ] `conversion` 模块仅消费 `algorithms` 提供的元信息,不反向定义算法层协议 -## M4. 算法层(以 max/min 为起点) +## M4. 算法层(traits 先行,以 max/min 为起点) ### 工作清单 +- [ ] 确定模块结构:`mcpplibs.primitives.algorithms`、`mcpplibs.primitives.algorithms.traits`、`mcpplibs.primitives.algorithms.compare`、`mcpplibs.primitives.algorithms.minmax` +- [ ] 先实现 `algorithms::traits` 与 `algorithms::common_traits`,作为整个算法层与 conversion 的基础依赖 +- [ ] 约束算法职责只涉及值的比较、选择、裁剪与边界处理,不提供目标类型导向的 cast API +- [ ] `max`/`min` 内部仅允许做 `common_rep` 归一化或排序语义协商,不绕回 conversion 层 - [ ] 实现 `max`/`min`,并预留 `clamp`/`compare` 扩展位 -- [ ] 算法统一依赖 M2+M3 的公开接口,不绕过转换层 -- [ ] 支持同类与受约束的异类输入 +- [ ] 支持同类输入与受约束的异类输入;异类场景必须满足 `common_rep`、排序能力与策略组约束 +- [ ] 明确 `partial_ordering` / `unordered` 语义,尤其是浮点 `NaN` 路径 +- [ ] 为 `clamp`/`compare` 抽出复用内核:公共比较、边界判定、值选择 - [ ] 在可行范围保持 `constexpr`/`noexcept` 特性 -- [ ] 增加边界测试(极值、NaN、有符号/无符号混合) +- [ ] 增加边界测试(极值、NaN、有符号/无符号混合、不同 `comparison_category`) ### 验收标准 - [ ] 算法行为与策略约束一致 - [ ] 风险路径始终显式、可审计 +- [ ] `algorithms` 可独立编译并被 `conversion` 依赖,不形成反向模块耦合 +- [ ] 算法层实现不通过“显式转换 API”间接完成值比较 ## 建议推进顺序 1. M2(先夯实约束与元信息基础) -2. M1(建立跨语言边界) -3. M3(收敛转换风险) -4. M4(复用基础能力实现算法) +2. M4 前半:`algorithms::traits` / `common_traits` / 排序能力查询 +3. M3(让 conversion 改为依赖 algorithms 元信息) +4. M4 后半:`max` / `min` / `clamp` / `compare` +5. M1(建立跨语言边界,可按需求并行推进) ## 总体完成跟踪 From 0fd165425f7f944c057c5c0400fdd3106c722ad3 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Thu, 26 Mar 2026 23:54:09 +0800 Subject: [PATCH 2/7] feat: Implement hash module for enhanced type hashing and value retrieval Signed-off-by: FrozenlemonTee <1115306170@qq.com> --- src/algorithms/hash.cppm | 79 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/algorithms/hash.cppm diff --git a/src/algorithms/hash.cppm b/src/algorithms/hash.cppm new file mode 100644 index 0000000..9cb8200 --- /dev/null +++ b/src/algorithms/hash.cppm @@ -0,0 +1,79 @@ +module; + +#include +#include +#include +#include + +export module mcpplibs.primitives.algorithms.hash; + +import mcpplibs.primitives.underlying; + +namespace mcpplibs::primitives::algorithms::details { + +template +concept std_hashable = requires(std::remove_cv_t const &value) { + { + std::hash>{}(value) + } -> std::convertible_to; +}; + +} // namespace mcpplibs::primitives::algorithms::details + +export namespace mcpplibs::primitives::algorithms { + +template struct hash { + using value_type = std::remove_cv_t; + using result_type = std::size_t; + + static constexpr bool enabled = false; + + auto operator()(value_type const &) const noexcept -> result_type { + return result_type{}; + } +}; + +template +using hash_result_t = hash>::result_type; + +template +concept hashable = hash>::enabled; + +template + requires details::std_hashable +struct hash { + using value_type = std::remove_cv_t; + using result_type = std::size_t; + + static constexpr bool enabled = true; + + auto operator()(value_type const &value) const noexcept( + noexcept(std::hash{}(value))) -> result_type { + return std::hash{}(value); + } +}; + +template + requires (!details::std_hashable && + hash>::rep_type>::enabled) +struct hash { + using value_type = std::remove_cv_t; + using rep_type = underlying::traits::rep_type; + using result_type = hash_result_t; + + static constexpr bool enabled = true; + + auto operator()(value_type const &value) const noexcept( + noexcept(hash{}(underlying::traits::to_rep(value)))) + -> result_type { + return hash{}(underlying::traits::to_rep(value)); + } +}; + +template +auto hash_value(T const &value) noexcept( + noexcept(hash>{}(value))) -> hash_result_t { + return hash>{}(value); +} + +} // namespace mcpplibs::primitives::algorithms From 6e44abf322961290ff1bc748ae949e31df77dee3 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Thu, 26 Mar 2026 23:54:23 +0800 Subject: [PATCH 3/7] feat: Add limits module for enhanced type limits and value retrieval Signed-off-by: FrozenlemonTee <1115306170@qq.com> --- src/algorithms/limits.cppm | 199 +++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 src/algorithms/limits.cppm diff --git a/src/algorithms/limits.cppm b/src/algorithms/limits.cppm new file mode 100644 index 0000000..9dc40dc --- /dev/null +++ b/src/algorithms/limits.cppm @@ -0,0 +1,199 @@ +module; + +#include +#include +#include + +export module mcpplibs.primitives.algorithms.limits; + +import mcpplibs.primitives.underlying; + +namespace mcpplibs::primitives::algorithms::details { + +template +concept has_numeric_limits = + std::numeric_limits>::is_specialized; + +template +consteval auto category_from_type() -> underlying::category { + using value_type = std::remove_cv_t; + if constexpr (std_bool) { + return underlying::category::boolean; + } else if constexpr (std_char) { + return underlying::category::character; + } else if constexpr (std::numeric_limits::is_integer) { + return underlying::category::integer; + } else { + return underlying::category::floating; + } +} + +} // namespace mcpplibs::primitives::algorithms::details + +export namespace mcpplibs::primitives::algorithms { + +template struct limits { + using value_type = std::remove_cv_t; + using rep_type = value_type; + + static constexpr bool enabled = false; + static constexpr bool is_specialized = false; + static constexpr bool is_bounded = false; + static constexpr bool is_exact = false; + static constexpr bool is_signed = false; + static constexpr bool is_integer = false; + static constexpr bool is_iec559 = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_nan = false; + static constexpr int digits = 0; + static constexpr int digits10 = 0; + static constexpr int radix = 0; + static constexpr auto kind = static_cast(-1); + + static constexpr auto min() noexcept -> value_type { return {}; } + static constexpr auto lowest() noexcept -> value_type { return {}; } + static constexpr auto max() noexcept -> value_type { return {}; } + static constexpr auto epsilon() noexcept -> value_type { return {}; } + static constexpr auto infinity() noexcept -> value_type { return {}; } + static constexpr auto quiet_nan() noexcept -> value_type { return {}; } +}; + +template + requires details::has_numeric_limits +struct limits { + using value_type = std::remove_cv_t; + using rep_type = value_type; + + static constexpr bool enabled = true; + static constexpr bool is_specialized = true; + static constexpr bool is_bounded = std::numeric_limits::is_bounded; + static constexpr bool is_exact = std::numeric_limits::is_exact; + static constexpr bool is_signed = std::numeric_limits::is_signed; + static constexpr bool is_integer = std::numeric_limits::is_integer; + static constexpr bool is_iec559 = std::numeric_limits::is_iec559; + static constexpr bool has_infinity = + std::numeric_limits::has_infinity; + static constexpr bool has_quiet_nan = + std::numeric_limits::has_quiet_NaN; + static constexpr int digits = std::numeric_limits::digits; + static constexpr int digits10 = std::numeric_limits::digits10; + static constexpr int radix = std::numeric_limits::radix; + static constexpr auto kind = details::category_from_type(); + + static constexpr auto min() noexcept -> value_type { + return std::numeric_limits::min(); + } + + static constexpr auto lowest() noexcept -> value_type { + return std::numeric_limits::lowest(); + } + + static constexpr auto max() noexcept -> value_type { + return std::numeric_limits::max(); + } + + static constexpr auto epsilon() noexcept -> value_type { + return std::numeric_limits::epsilon(); + } + + static constexpr auto infinity() noexcept -> value_type { + return std::numeric_limits::infinity(); + } + + static constexpr auto quiet_nan() noexcept -> value_type { + return std::numeric_limits::quiet_NaN(); + } +}; + +template + requires (!details::has_numeric_limits && + !std::same_as, + typename underlying::traits>::rep_type> && + limits>::rep_type>::enabled) +struct limits { + using value_type = std::remove_cv_t; + using rep_type = underlying::traits::rep_type; + using rep_limits = limits; + + static constexpr bool enabled = true; + static constexpr bool is_specialized = rep_limits::is_specialized; + static constexpr bool is_bounded = rep_limits::is_bounded; + static constexpr bool is_exact = rep_limits::is_exact; + static constexpr bool is_signed = rep_limits::is_signed; + static constexpr bool is_integer = rep_limits::is_integer; + static constexpr bool is_iec559 = rep_limits::is_iec559; + static constexpr bool has_infinity = rep_limits::has_infinity; + static constexpr bool has_quiet_nan = rep_limits::has_quiet_nan; + static constexpr int digits = rep_limits::digits; + static constexpr int digits10 = rep_limits::digits10; + static constexpr int radix = rep_limits::radix; + static constexpr auto kind = underlying::traits::kind; + + static constexpr auto min() noexcept -> value_type { + return underlying::traits::from_rep(rep_limits::min()); + } + + static constexpr auto lowest() noexcept -> value_type { + return underlying::traits::from_rep(rep_limits::lowest()); + } + + static constexpr auto max() noexcept -> value_type { + return underlying::traits::from_rep(rep_limits::max()); + } + + static constexpr auto epsilon() noexcept -> value_type { + return underlying::traits::from_rep(rep_limits::epsilon()); + } + + static constexpr auto infinity() noexcept -> value_type { + return underlying::traits::from_rep(rep_limits::infinity()); + } + + static constexpr auto quiet_nan() noexcept -> value_type { + return underlying::traits::from_rep(rep_limits::quiet_nan()); + } +}; + +template +concept limited_type = limits>::enabled; + +template +using limit_value_t = limits>::value_type; + +template +constexpr auto min_value() noexcept( + noexcept(limits>::min())) -> limit_value_t { + return limits>::min(); +} + +template +constexpr auto lowest_value() noexcept( + noexcept(limits>::lowest())) -> limit_value_t { + return limits>::lowest(); +} + +template +constexpr auto max_value() noexcept( + noexcept(limits>::max())) -> limit_value_t { + return limits>::max(); +} + +template +constexpr auto epsilon_value() noexcept( + noexcept(limits>::epsilon())) -> limit_value_t { + return limits>::epsilon(); +} + +template +constexpr auto infinity_value() noexcept( + noexcept(limits>::infinity())) -> limit_value_t { + return limits>::infinity(); +} + +template +constexpr auto quiet_nan_value() noexcept( + noexcept(limits>::quiet_nan())) -> limit_value_t { + return limits>::quiet_nan(); +} + +} // namespace mcpplibs::primitives::algorithms From 3e03ce858a1ba53c25a5a80ed0333f222f657cfd Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Thu, 26 Mar 2026 23:54:35 +0800 Subject: [PATCH 4/7] feat: Add algorithms module for enhanced algorithmic operations and imports Signed-off-by: FrozenlemonTee <1115306170@qq.com> --- src/algorithms/algorithms.cppm | 6 ++++++ src/primitives.cppm | 1 + 2 files changed, 7 insertions(+) create mode 100644 src/algorithms/algorithms.cppm diff --git a/src/algorithms/algorithms.cppm b/src/algorithms/algorithms.cppm new file mode 100644 index 0000000..9ba3474 --- /dev/null +++ b/src/algorithms/algorithms.cppm @@ -0,0 +1,6 @@ +module; + +export module mcpplibs.primitives.algorithms; + +export import mcpplibs.primitives.algorithms.hash; +export import mcpplibs.primitives.algorithms.limits; diff --git a/src/primitives.cppm b/src/primitives.cppm index 6d53dc5..cfa671f 100644 --- a/src/primitives.cppm +++ b/src/primitives.cppm @@ -6,4 +6,5 @@ export import mcpplibs.primitives.underlying; export import mcpplibs.primitives.policy; export import mcpplibs.primitives.primitive; export import mcpplibs.primitives.operations; +export import mcpplibs.primitives.algorithms; export import mcpplibs.primitives.conversion; From 7e21e4e50156614e186a66627cff4224208c7790 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Thu, 26 Mar 2026 23:54:48 +0800 Subject: [PATCH 5/7] feat: Add tests for algorithms module including hash and limits functionality Signed-off-by: FrozenlemonTee <1115306170@qq.com> --- tests/basic/CMakeLists.txt | 2 + tests/basic/algorithms/hash/test_hash.cpp | 35 +++++++++++ tests/basic/algorithms/limits/test_limits.cpp | 63 +++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 tests/basic/algorithms/hash/test_hash.cpp create mode 100644 tests/basic/algorithms/limits/test_limits.cpp diff --git a/tests/basic/CMakeLists.txt b/tests/basic/CMakeLists.txt index 5e199b2..2cfd3a7 100644 --- a/tests/basic/CMakeLists.txt +++ b/tests/basic/CMakeLists.txt @@ -28,6 +28,7 @@ function(add_basic_suite target_name suite_pattern) endfunction() add_basic_suite(basic_conversion_tests "conversion/**/test_*.cpp") +add_basic_suite(basic_algorithms_tests "algorithms/**/test_*.cpp") add_basic_suite(basic_operations_tests "operations/**/test_*.cpp") add_basic_suite(basic_policy_tests "policy/**/test_*.cpp") add_basic_suite(basic_primitive_tests "primitive/**/test_*.cpp") @@ -36,6 +37,7 @@ add_basic_suite(basic_underlying_tests "underlying/**/test_*.cpp") add_custom_target(basic_tests) add_dependencies(basic_tests basic_conversion_tests + basic_algorithms_tests basic_operations_tests basic_policy_tests basic_primitive_tests diff --git a/tests/basic/algorithms/hash/test_hash.cpp b/tests/basic/algorithms/hash/test_hash.cpp new file mode 100644 index 0000000..fa50377 --- /dev/null +++ b/tests/basic/algorithms/hash/test_hash.cpp @@ -0,0 +1,35 @@ +#include +#include +#include + +import mcpplibs.primitives.algorithms; +import mcpplibs.primitives.underlying; + +#include "../../support/underlying_custom_types.hpp" + +using namespace mcpplibs::primitives; +using namespace mcpplibs::primitives::test_support::underlying; + +TEST(AlgorithmHashTest, BuiltinHashDelegatesToStdHash) { + static_assert(algorithms::hashable); + static_assert(std::same_as, std::size_t>); + + auto const value = 42; + EXPECT_EQ(algorithms::hash{}(value), std::hash{}(value)); + EXPECT_EQ(algorithms::hash_value(value), std::hash{}(value)); +} + +TEST(AlgorithmHashTest, CustomUnderlyingHashesThroughRepType) { + static_assert(algorithms::hashable); + + auto const value = UserInteger{42}; + auto const expected = std::hash{}(42); + + EXPECT_EQ(algorithms::hash{}(value), expected); + EXPECT_EQ(algorithms::hash_value(value), expected); +} + +TEST(AlgorithmHashTest, UnsupportedSelfRepresentedRepRemainsDisabled) { + static_assert(!algorithms::hashable); + SUCCEED(); +} diff --git a/tests/basic/algorithms/limits/test_limits.cpp b/tests/basic/algorithms/limits/test_limits.cpp new file mode 100644 index 0000000..b3301c9 --- /dev/null +++ b/tests/basic/algorithms/limits/test_limits.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include + +import mcpplibs.primitives.algorithms; +import mcpplibs.primitives.underlying; + +#include "../../support/underlying_custom_types.hpp" + +using namespace mcpplibs::primitives; +using namespace mcpplibs::primitives::test_support::underlying; + +TEST(AlgorithmLimitsTest, BuiltinIntegerLimitsFollowNumericLimitsShape) { + using limits_t = algorithms::limits; + + static_assert(limits_t::enabled); + static_assert(limits_t::is_specialized); + static_assert(std::same_as); + static_assert(limits_t::kind == underlying::category::integer); + static_assert(limits_t::digits == std::numeric_limits::digits); + static_assert(limits_t::radix == std::numeric_limits::radix); + static_assert(algorithms::limited_type); + + EXPECT_EQ(limits_t::lowest(), std::numeric_limits::lowest()); + EXPECT_EQ(limits_t::max(), std::numeric_limits::max()); + EXPECT_EQ(algorithms::min_value(), std::numeric_limits::min()); +} + +TEST(AlgorithmLimitsTest, BuiltinFloatingLimitsExposeSpecialValues) { + using limits_t = algorithms::limits; + + static_assert(limits_t::enabled); + static_assert(limits_t::has_quiet_nan); + static_assert(limits_t::has_infinity); + static_assert(limits_t::kind == underlying::category::floating); + static_assert(limits_t::is_iec559); + + EXPECT_EQ(algorithms::epsilon_value(), + std::numeric_limits::epsilon()); + EXPECT_EQ(algorithms::infinity_value(), + std::numeric_limits::infinity()); + EXPECT_TRUE(std::isnan(algorithms::quiet_nan_value())); +} + +TEST(AlgorithmLimitsTest, CustomUnderlyingUsesRepBackedLimits) { + using limits_t = algorithms::limits; + + static_assert(limits_t::enabled); + static_assert(std::same_as); + static_assert(limits_t::kind == underlying::category::integer); + + EXPECT_EQ(underlying::traits::to_rep(limits_t::lowest()), + std::numeric_limits::lowest()); + EXPECT_EQ(underlying::traits::to_rep(limits_t::max()), + std::numeric_limits::max()); +} + +TEST(AlgorithmLimitsTest, SelfRepresentedCustomRepNeedsExplicitLimitsSpecialization) { + static_assert(!algorithms::limits::enabled); + SUCCEED(); +} From 314b19a7285d12450258112f510bd1f1660cda71 Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Fri, 27 Mar 2026 00:03:19 +0800 Subject: [PATCH 6/7] feat: Replace std::numeric_limits with algorithms module for improved type limits handling Signed-off-by: FrozenlemonTee <1115306170@qq.com> --- src/conversion/underlying.cppm | 34 ++++++++++++------------- src/operations/invoker.cppm | 46 +++++++++++++++++----------------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/conversion/underlying.cppm b/src/conversion/underlying.cppm index 8563588..07129fb 100644 --- a/src/conversion/underlying.cppm +++ b/src/conversion/underlying.cppm @@ -3,12 +3,12 @@ module; #include #include #include -#include #include #include export module mcpplibs.primitives.conversion.underlying; +import mcpplibs.primitives.algorithms.limits; import mcpplibs.primitives.conversion.traits; import mcpplibs.primitives.underlying; @@ -65,11 +65,11 @@ constexpr auto numeric_risk(SrcRep value) auto const signed_value = static_cast(value); if constexpr (std::is_signed_v) { if (signed_value < - static_cast(std::numeric_limits::min())) { + static_cast(algorithms::min_value())) { return risk::kind::underflow; } if (signed_value > - static_cast(std::numeric_limits::max())) { + static_cast(algorithms::max_value())) { return risk::kind::overflow; } return std::nullopt; @@ -80,7 +80,7 @@ constexpr auto numeric_risk(SrcRep value) if (static_cast(signed_value) > static_cast( - std::numeric_limits::max())) { + algorithms::max_value())) { return risk::kind::overflow; } return std::nullopt; @@ -88,7 +88,7 @@ constexpr auto numeric_risk(SrcRep value) } else { auto const unsigned_value = static_cast(value); if (unsigned_value > - static_cast(std::numeric_limits::max())) { + static_cast(algorithms::max_value())) { return risk::kind::overflow; } return std::nullopt; @@ -104,9 +104,9 @@ constexpr auto numeric_risk(SrcRep value) auto const normalized = static_cast(value); auto const min_value = - static_cast(std::numeric_limits::lowest()); + static_cast(algorithms::lowest_value()); auto const max_value = - static_cast(std::numeric_limits::max()); + static_cast(algorithms::max_value()); if (normalized < min_value) { return risk::kind::underflow; @@ -135,9 +135,9 @@ constexpr auto numeric_risk(SrcRep value) auto const normalized = static_cast(value); auto const min_value = - static_cast(std::numeric_limits::lowest()); + static_cast(algorithms::lowest_value()); auto const max_value = - static_cast(std::numeric_limits::max()); + static_cast(algorithms::max_value()); if (normalized < min_value) { return risk::kind::underflow; @@ -216,10 +216,10 @@ constexpr auto saturating_rep_cast(SrcRep value) noexcept if constexpr (std_numeric && std_numeric) { if (auto const kind = numeric_risk(value); kind.has_value()) { if (*kind == risk::kind::overflow) { - return std::numeric_limits::max(); + return algorithms::max_value(); } if (*kind == risk::kind::underflow) { - return std::numeric_limits::lowest(); + return algorithms::lowest_value(); } if (*kind == risk::kind::domain_error) { return dest_type{}; @@ -243,21 +243,21 @@ constexpr auto truncating_rep_cast(SrcRep value) noexcept } if (std::isinf(value)) { return value < static_cast(0) - ? std::numeric_limits::lowest() - : std::numeric_limits::max(); + ? algorithms::lowest_value() + : algorithms::max_value(); } auto const normalized = static_cast(value); auto const min_value = - static_cast(std::numeric_limits::lowest()); + static_cast(algorithms::lowest_value()); auto const max_value = - static_cast(std::numeric_limits::max()); + static_cast(algorithms::max_value()); if (normalized < min_value) { - return std::numeric_limits::lowest(); + return algorithms::lowest_value(); } if (normalized > max_value) { - return std::numeric_limits::max(); + return algorithms::max_value(); } } diff --git a/src/operations/invoker.cppm b/src/operations/invoker.cppm index 87c4258..7bd53fa 100644 --- a/src/operations/invoker.cppm +++ b/src/operations/invoker.cppm @@ -4,13 +4,13 @@ module; #include #include #include -#include #include #include #include export module mcpplibs.primitives.operations.invoker; +import mcpplibs.primitives.algorithms.limits; import mcpplibs.primitives.operations.traits; import mcpplibs.primitives.operations.impl; import mcpplibs.primitives.policy.handler; @@ -42,7 +42,7 @@ constexpr auto checked_add(T lhs, T rhs) -> policy::value::decision { out.value = static_cast(lhs + rhs); return out; } else if constexpr (std::is_unsigned_v) { - auto const maxv = std::numeric_limits::max(); + auto const maxv = algorithms::max_value(); if (lhs > maxv - rhs) { return make_error(policy::error::kind::overflow, "checked addition overflow", lhs, rhs); @@ -52,8 +52,8 @@ constexpr auto checked_add(T lhs, T rhs) -> policy::value::decision { out.value = static_cast(lhs + rhs); return out; } else { - auto const maxv = std::numeric_limits::max(); - auto const minv = std::numeric_limits::min(); + auto const maxv = algorithms::max_value(); + auto const minv = algorithms::min_value(); if ((rhs > 0) && (lhs > maxv - rhs)) { return make_error(policy::error::kind::overflow, "checked addition overflow", lhs, rhs); @@ -86,8 +86,8 @@ constexpr auto checked_sub(T lhs, T rhs) -> policy::value::decision { out.value = static_cast(lhs - rhs); return out; } else { - auto const maxv = std::numeric_limits::max(); - auto const minv = std::numeric_limits::min(); + auto const maxv = algorithms::max_value(); + auto const minv = algorithms::min_value(); if ((rhs < 0) && (lhs > maxv + rhs)) { return make_error(policy::error::kind::overflow, "checked subtraction overflow", lhs, rhs); @@ -119,7 +119,7 @@ constexpr auto checked_mul(T lhs, T rhs) -> policy::value::decision { } if constexpr (std::is_unsigned_v) { - auto const maxv = std::numeric_limits::max(); + auto const maxv = algorithms::max_value(); if (lhs > maxv / rhs) { return make_error(policy::error::kind::overflow, "checked multiplication overflow", lhs, rhs); @@ -129,8 +129,8 @@ constexpr auto checked_mul(T lhs, T rhs) -> policy::value::decision { out.value = static_cast(lhs * rhs); return out; } else { - auto const maxv = std::numeric_limits::max(); - auto const minv = std::numeric_limits::min(); + auto const maxv = algorithms::max_value(); + auto const minv = algorithms::min_value(); if (lhs > 0) { if (rhs > 0) { @@ -174,7 +174,7 @@ constexpr auto checked_div(T lhs, T rhs) -> policy::value::decision { } if constexpr (std::is_integral_v && std::is_signed_v) { - auto const minv = std::numeric_limits::min(); + auto const minv = algorithms::min_value(); if (lhs == minv && rhs == static_cast(-1)) { return make_error(policy::error::kind::overflow, "checked division overflow", lhs, rhs); @@ -212,7 +212,7 @@ constexpr auto checked_mod(T lhs, T rhs) -> policy::value::decision { } if constexpr (std::is_signed_v) { - auto const minv = std::numeric_limits::min(); + auto const minv = algorithms::min_value(); if (lhs == minv && rhs == static_cast(-1)) { return make_error(policy::error::kind::overflow, "checked modulus overflow", lhs, rhs); @@ -242,7 +242,7 @@ constexpr auto checked_unary_plus(T lhs) -> policy::value::decision { template constexpr auto checked_unary_minus(T lhs) -> policy::value::decision { if constexpr (std::is_integral_v && std::is_signed_v) { - auto const minv = std::numeric_limits::min(); + auto const minv = algorithms::min_value(); if (lhs == minv) { return make_error(policy::error::kind::overflow, "checked unary minus overflow", lhs); @@ -269,7 +269,7 @@ constexpr auto checked_shift_left(T lhs, T rhs) -> policy::value::decision { rhs); } else { using unsigned_t = std::make_unsigned_t; - constexpr auto bit_width = std::numeric_limits::digits; + constexpr auto bit_width = algorithms::limits::digits; if constexpr (std::is_signed_v) { if (rhs < T{}) { @@ -290,7 +290,7 @@ constexpr auto checked_shift_left(T lhs, T rhs) -> policy::value::decision { "checked left shift negative lhs", lhs, rhs); } - auto const maxv = std::numeric_limits::max(); + auto const maxv = algorithms::max_value(); if (lhs > static_cast(maxv >> shift)) { return make_error(policy::error::kind::overflow, "checked left shift overflow", lhs, rhs); @@ -314,7 +314,7 @@ constexpr auto checked_shift_right(T lhs, T rhs) rhs); } else { using unsigned_t = std::make_unsigned_t; - constexpr auto bit_width = std::numeric_limits::digits; + constexpr auto bit_width = algorithms::limits::digits; if constexpr (std::is_signed_v) { if (rhs < T{}) { @@ -681,11 +681,11 @@ template constexpr auto saturating_add(T lhs, T rhs) -> T { if constexpr (!std::is_integral_v || std::is_same_v) { return static_cast(lhs + rhs); } else if constexpr (std::is_unsigned_v) { - auto const maxv = std::numeric_limits::max(); + auto const maxv = algorithms::max_value(); return (lhs > maxv - rhs) ? maxv : static_cast(lhs + rhs); } else { - auto const maxv = std::numeric_limits::max(); - auto const minv = std::numeric_limits::min(); + auto const maxv = algorithms::max_value(); + auto const minv = algorithms::min_value(); if ((rhs > 0) && (lhs > maxv - rhs)) { return maxv; } @@ -702,8 +702,8 @@ template constexpr auto saturating_sub(T lhs, T rhs) -> T { } else if constexpr (std::is_unsigned_v) { return (lhs < rhs) ? T{} : static_cast(lhs - rhs); } else { - auto const maxv = std::numeric_limits::max(); - auto const minv = std::numeric_limits::min(); + auto const maxv = algorithms::max_value(); + auto const minv = algorithms::min_value(); if ((rhs < 0) && (lhs > maxv + rhs)) { return maxv; } @@ -723,11 +723,11 @@ template constexpr auto saturating_mul(T lhs, T rhs) -> T { } if constexpr (std::is_unsigned_v) { - auto const maxv = std::numeric_limits::max(); + auto const maxv = algorithms::max_value(); return (lhs > maxv / rhs) ? maxv : static_cast(lhs * rhs); } else { - auto const maxv = std::numeric_limits::max(); - auto const minv = std::numeric_limits::min(); + auto const maxv = algorithms::max_value(); + auto const minv = algorithms::min_value(); if (lhs > 0) { if (rhs > 0) { From 43bcc15130e858696dc1faccbad1363c60697fde Mon Sep 17 00:00:00 2001 From: FrozenlemonTee <1115306170@qq.com> Date: Fri, 27 Mar 2026 00:16:58 +0800 Subject: [PATCH 7/7] feat: Enhance hash module with additional type constraints for improved hashing functionality Signed-off-by: FrozenlemonTee <1115306170@qq.com> --- src/algorithms/hash.cppm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/algorithms/hash.cppm b/src/algorithms/hash.cppm index 9cb8200..f59d80d 100644 --- a/src/algorithms/hash.cppm +++ b/src/algorithms/hash.cppm @@ -55,6 +55,8 @@ struct hash { template requires (!details::std_hashable && + !std::same_as, + typename underlying::traits>::rep_type> && hash>::rep_type>::enabled) struct hash { using value_type = std::remove_cv_t;