Skip to content

Commit 298978f

Browse files
Merge pull request #5 from mcpplibs/refactor-operations
Bump version to 0.2.0
2 parents a8546f4 + d1006cb commit 298978f

32 files changed

+3099
-1262
lines changed

.agents/docs/architecture.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ graph TD
4949

5050
## 命名空间与 API 边界
5151

52+
### 标准库依赖使用方式
53+
54+
由于`import std;`在目前 CMake 的构建系统中属于实验性特性,故使用标准库依赖仍然采用头文件方式。
55+
使用的预处理指令放于模块源文件的全局模块部分,示例:
56+
```c++
57+
module;
58+
#include <type_traits>
59+
#include <concepts>
60+
61+
export module mcpplibs.primitives.submodule;
62+
63+
export namespace mcpplibs::primitives::subnamepsace {
64+
// Implements
65+
}
66+
```
67+
5268
### 公共 API(导出,稳定承诺)
5369
5470
- `mcpplibs::primitives::std_bool`
@@ -62,7 +78,7 @@ graph TD
6278
6379
### 内部实现(不导出,不承诺稳定)
6480
65-
- `mcpplibs::primitives::underlying::details::*`
81+
- `mcpplibs::primitives::**::details::*`
6682
6783
### 约定
6884

.github/copilot-instructions.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
- 技能目录: `../.agents/skills/`
1313
- mcpp-style-ref: `../.agents/skills/mcpp-style-ref/SKILL.md`
1414

15+
## 正在进行中的计划
16+
17+
- 计划目录:`../.github/prompts/`
18+
- 当前计划:`../.github/prompts/plan-policyBehaviorProtocol.prompt.md`
19+
1520
## 说明
1621

1722
- 新增或调整 Copilot 约束时,优先更新 `.agents/docs``.agents/skills`
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
## Plan: Policy 行为协议与分发规范
2+
3+
基于现有 traits/concept 架构,采用“policy handler 协议 + 固定 dispatcher + primitive 路由层”的设计。type 协商前移到编译期静态决议,运行期 dispatcher 固定为三层并按外到内调用:concurrency -> value(已知 common type)-> error。第一阶段覆盖四则运算(加减乘除),错误通道统一为 expected 返回;跨底层类型运算由 type policy 在编译期决定“是否允许 + common type”;value 层负责溢出判定与值调整/错误下放且需要接收 concurrency 层注入;error 层按策略执行最终错误处理。用户扩展边界限定为仅可特化 policy handler,以保持上层接口可复用、低耦合且强约束。
4+
5+
**Steps**
6+
1. 明确协议核心抽象(阻塞后续步骤)
7+
2. 在 policy 层定义行为协议接口(依赖步骤 1)
8+
3. 在 operations 层建立统一分发入口(依赖步骤 2)
9+
4. 在 primitive 层实现运算路由与返回类型统一(依赖步骤 3)
10+
5. 为跨类型运算定义 type policy 协商规则(依赖步骤 4,部分可与步骤 6 并行)
11+
6. 建立编译期约束与诊断信息(依赖步骤 2,可并行于步骤 5)
12+
7. 增加测试矩阵与示例验证(依赖步骤 4、5、6)
13+
8. 文档化协议与扩展边界(依赖步骤 7)
14+
15+
**Phase 1: 协议基线(接口层)**
16+
1.[src/policy/traits.cppm](src/policy/traits.cppm) 复用 category 与 policy_type 概念,新增“行为协议概念”所需的基础类型约束(仅声明契约,不放具体行为)。
17+
2.[src/policy/impl.cppm](src/policy/impl.cppm) 保留现有标签与 traits 特化,补充“策略能力声明位”对应的 traits 扩展位(用于编译期判定策略是否实现某 operation)。
18+
3. 新增 policy 协议模块(建议命名 mcpplibs.primitives.policy.handler),内容包含:
19+
4. `policy_handler<Policy, OperationTag, Lhs, Rhs>` 主模板(默认禁用)
20+
5. `policy_handler_available` 概念(用于约束上层调用)
21+
6. 标准返回别名(统一为 expected 语义)
22+
7. 明确用户扩展点:只允许特化 handler,不开放分发规则特化。
23+
24+
**Phase 2: Operation 分发层(固定三层运行期链路)**
25+
1.[src/operations/impl.cppm](src/operations/impl.cppm) 维持 operation tag + arity 元数据,增加“可分发 operation”约束入口(例如合法 operation 概念)。
26+
2.[src/operations/operators.cppm](src/operations/operators.cppm) 将 type 协商前移为编译期预处理,并实现运行期固定 dispatcher:
27+
3. concurrency handler:负责并发包装(如加锁/解锁、内存屏障注入;具体机制可后续细化),并向 value 层注入并发执行上下文。
28+
4. value handler:接收已决议的 common type + concurrency 注入上下文,在 common type 上执行值域与溢出判定,决定“本层修正结果值”或“下放错误处理请求”。
29+
5. error handler:接收上层错误请求并按策略完成最终处理,统一映射到 expected 错误值。
30+
6. dispatcher 对外统一返回 expected,且不依赖具体 primitive 别名,仅依赖 traits 协议。
31+
32+
**Phase 3: Primitive 路由层(上层调用面)**
33+
1.[src/primitive/traits.cppm](src/primitive/traits.cppm) 复用 primitive_traits 与 resolve_policy_t,新增:
34+
2. 跨类型运算协商 trait(由 type policy 决定是否允许、结果 common type)
35+
3. 结果 primitive 重建工具(保持策略传播一致)
36+
4. 在 primitive 对外运算入口中接入 operations dispatcher,覆盖加减乘除四个操作。
37+
5. 返回类型统一为 expected(成功值为 primitive,失败值为错误域类型)。
38+
39+
**Phase 4: 聚合导出与契约稳定**
40+
1.[src/primitives.cppm](src/primitives.cppm) 增加新协议模块与分发层导出,保持聚合入口一致。
41+
2.[src/policy/utility.cppm](src/policy/utility.cppm) 保持 common policy 选择逻辑不变,仅补充与 handler 可用性相关的辅助别名(若需要)。
42+
43+
**Phase 5: 验证与回归**
44+
1.[tests](tests) 新增 policy 行为协议测试:
45+
2. handler 未实现时应在编译期失败(约束强)
46+
3. 四则运算均返回 expected
47+
4. 相同 type policy 下跨类型协商正确/错误路径正确
48+
5.[examples/basic.cpp](examples/basic.cpp) 增加最小示例:
49+
6. 默认策略下四则运算
50+
7. 自定义 policy handler 的单点扩展示例(仅特化 handler)
51+
52+
53+
**Interface Contracts(最小签名清单)**
54+
1. Dispatcher 总入口(放在 [src/operations/operators.cppm](src/operations/operators.cppm)):
55+
2. 输入:OperationTag、Lhs Primitive、Rhs Primitive、四类 policy(由 primitive_traits 解析)。
56+
3. 输出:expected<ResultPrimitive, ErrorPayload>。
57+
4. 约束:type 协商在编译期完成;运行期调用顺序固定为 concurrency -> value -> error。
58+
5. 编译期 type 协商合约(静态层,不进入运行期链路):
59+
6. 输入:操作标签、Lhs/Rhs 静态类型信息、type policy。
60+
7. 输出:type_decision(is_allowed、common_type、diagnostic_id)。
61+
8. 责任:拒绝非法运算并确定 common_type;其结果作为运行期 value 层输入前提。
62+
9. concurrency handler 合约(放在 policy handler 模块):
63+
10. 输入:operation_context、下一层 continuation、type_decision。
64+
11. 输出:concurrency_injection + 下一层 expected 透传能力。
65+
12. 责任:加锁/解锁、内存屏障、线程可见性包装;向 value 层注入并发执行上下文,不做值域判定。
66+
13. value handler 合约:
67+
14. 输入:common_type 下的 lhs/rhs、operation_context、concurrency_injection。
68+
15. 输出:二选一路径:
69+
16. 路径 A:直接给出成功值(已修正或原值)。
70+
17. 路径 B:下发 error_request(包含错误类别、上下文、候选回退值)。
71+
18. 责任:执行溢出/下溢/除零等值域检查,并决定是否本层修正。
72+
19. error handler 合约:
73+
20. 输入:error_request + operation_context。
74+
21. 输出:expected<ResultPrimitive, ErrorPayload> 的最终错误分支或恢复成功值分支。
75+
22. 责任:按 error policy 落地处理(例如映射错误域、终止、抛错转译为 expected 错误值)。
76+
23. 跨层数据结构建议:
77+
24. operation_context:封装 op tag、源 primitive traits、policy 句柄、调试标签。
78+
25. type_decision:封装 is_allowed、common_type、diagnostic_id。
79+
26. concurrency_injection:封装 guard_handle、memory_order/屏障策略、可选调度标签。
80+
27. value_decision:封装 has_value、value、error_request。
81+
28. error_request:封装 error_kind、reason、operation_context、可选 fallback。
82+
29. 扩展边界:
83+
30. 用户只可特化三类运行期 handler(concurrency/value/error)与静态 type 协商策略实现,不可替换 dispatcher 顺序、不可改动跨层数据结构主骨架。
84+
85+
**Relevant files**
86+
- [src/policy/traits.cppm](src/policy/traits.cppm) — 复用并扩展 policy 概念边界,承载行为协议约束基础。
87+
- [src/policy/impl.cppm](src/policy/impl.cppm) — 保持标签定义,补充策略能力元信息挂点。
88+
- [src/policy/utility.cppm](src/policy/utility.cppm) — 与 common_policies 选择逻辑对齐,必要时提供 handler 检查辅助。
89+
- [src/operations/impl.cppm](src/operations/impl.cppm) — operation 元数据与分发前置约束。
90+
- [src/operations/operators.cppm](src/operations/operators.cppm) — dispatcher 核心实现位置。
91+
- [src/primitive/traits.cppm](src/primitive/traits.cppm) — policy 解析与跨类型协商 trait 的主落点。
92+
- [src/primitives.cppm](src/primitives.cppm) — 对外聚合导出。
93+
- [tests](tests) — 编译期约束与行为结果验证。
94+
- [examples/basic.cpp](examples/basic.cpp) — API 用法与扩展示例。
95+
96+
**Verification**
97+
1. 编译期契约验证:
98+
2. 未提供对应 policy_handler 的 operation 调用必须报清晰静态断言。
99+
3. type policy 禁止的跨类型运算必须在编译期拒绝。
100+
4. 固定链路验证:
101+
5. type 协商必须在编译期完成,运行期 dispatcher 必须按 concurrency -> value -> error 顺序调用,禁止跳层与重排。
102+
6. value 层必须验证“接收 concurrency 注入”这一前提生效。
103+
7. value 层“值修正”与“错误下放”两条路径都需覆盖测试。
104+
8. 行为一致性验证:
105+
9. 四则运算对默认策略与自定义策略均返回 expected。
106+
10. 失败路径(溢出/除零/不兼容类型)按 error policy 语义编码到 expected 错误值。
107+
11. unchecked_value 路径验证:
108+
12. 不触发 error policy,保持原生算术语义(含 UB 风险)并通过测试明确边界。
109+
13. 导出稳定性验证:
110+
14. 通过聚合模块导入可直接访问 policy 协议、operation 分发、primitive 运算。
111+
15. 运行 tests 与示例构建,确认无回归。
112+
113+
**Decisions**
114+
- 错误通道:默认路径统一返回 expected。
115+
- dispatcher 形态:type 协商前移到编译期,运行期固定三层链路 concurrency -> value -> error,不开放顺序重排。
116+
- 跨底层类型运算:由 type policy 在编译期决定可行性与 common type。
117+
- value 层职责:判定溢出并决定“本层值修正”或“下放 error 层处理”。
118+
- unchecked_value 语义:不做错误处理,不调用 error policy,行为尽量贴近原生 C/C++(包含 UB 风险)。
119+
- 扩展边界:仅开放 policy handler 特化,不开放分发规则。
120+
- 第一阶段覆盖范围:Addition/Subtraction/Multiplication/Division 全部纳入。
121+
- In scope:policy 行为协议、operation 分发、primitive 路由、测试与文档。
122+
- Out of scope:并发策略的运行时同步原语实现细节(atomic/lock-free/锁策略具体执行体)。
123+
124+
## Underlying Bridge Execution Contract (Runtime)
125+
126+
1. `dispatch` 在 value 阶段前统一执行 `to_rep`,将原始 value 映射到可协商的 `rep_type`
127+
2. `type_handler` 的协商对象是 `lhs_rep/rhs_rep`,而非原始 value type。
128+
3. 若任一输入 `is_valid_rep(...) == false`,立即构造 `runtime_error_kind::domain_error` 并进入 error policy。
129+
4. 通过校验后执行 `from_rep -> to_rep` 规范化,再进入 value handler 与 op binding。
130+
5. 当前结果值仍按 `common_rep` 回传;comparison 最小闭环采用 `0/1` 表示(`static_cast<common_rep>(bool)`)。
131+
6. 本契约不改变 dispatcher 链路顺序,也不改变错误枚举体系。
132+
133+
**Further Considerations**
134+
1. expected 的错误载体类型建议先统一为轻量错误枚举,再逐步演进到可扩展错误域,以减少首版模板复杂度。
135+
2. type policy 的 common type 规则建议先采用“显式白名单 + static_assert 诊断”,避免首版引入过宽的隐式提升。
136+
3. 后续可新增“native 快速路径”作为可选 API:当组合为 primitive<unchecked_value, transparent_type, single_thread> 时,提供非 expected 返回通道以最大化贴近原生 C/C++ 性能与行为。
137+
4. 后续可新增 C API 适配层(extern "C" 薄封装,POD 入参与返回值),内部复用 unchecked/native 路径,优先保障与现有 C 调用约定兼容。

CMakeLists.txt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 23)
66
set(CMAKE_CXX_STANDARD_REQUIRED ON)
77
set(CMAKE_CXX_EXTENSIONS OFF)
88

9-
project(mcpplibs-primitives VERSION 0.1.0 LANGUAGES CXX)
9+
project(mcpplibs-primitives VERSION 0.2.0 LANGUAGES CXX)
1010

1111
find_package(Threads REQUIRED)
1212

@@ -36,7 +36,7 @@ endif()
3636
# Library
3737
add_library(mcpplibs-primitives STATIC)
3838

39-
file(GLOB_RECURSE CXX_MODULE_FILES
39+
file(GLOB_RECURSE CXX_MODULE_FILES CONFIGURE_DEPENDS
4040
src/*.cppm
4141
)
4242

@@ -60,8 +60,7 @@ target_include_directories(mcpplibs-primitives PUBLIC
6060
)
6161

6262
# Examples
63-
add_executable(basic examples/basic.cpp)
64-
target_link_libraries(basic PRIVATE mcpplibs-primitives)
63+
add_subdirectory(examples EXCLUDE_FROM_ALL)
6564

6665
# Testing
6766
option(BUILD_TESTING "Build the testing directories" ON)

README.md

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919

2020
该库在 `primitive` 类型上重载了常见的 C++ 算术、位运算和一元运算符。算术行为受策略(policy)控制:
2121

22-
- 值策略(`checked_value` / `saturating_value` / `unchecked_value`)决定溢出行为;
23-
- 错误策略(`throw_error` / `expected_error` / `terminate_error`)决定在 `checked_value` 且发生错误时的处理方式。
22+
- 值策略(`policy::value::checked` / `policy::value::saturating` / `policy::value::unchecked`)决定溢出行为;
23+
- 错误策略(`policy::error::throwing` / `policy::error::expected` / `policy::error::terminate`)决定在 `policy::value::checked` 且发生错误时的处理方式。
2424

2525
示例:
2626

@@ -32,11 +32,35 @@ using namespace mcpplibs::primitives::policy;
3232
primitive<int> a{1}, b{2};
3333
auto c = a + b; // primitive<int>
3434

35-
primitive<int, expected_error> x{std::numeric_limits<int>::max()};
36-
primitive<int, expected_error> y{1};
37-
auto maybe = x + y; // std::expected<primitive<int, expected_error>, std::overflow_error>
35+
primitive<int, policy::error::expected> x{std::numeric_limits<int>::max()};
36+
primitive<int, policy::error::expected> y{1};
37+
auto maybe = x + y; // std::expected<primitive<int, policy::error::expected>, policy::error::kind>
3838
```
3939
40+
## Policy 协议命名空间
41+
42+
自定义 policy 时,协议入口已按职责拆分到子命名空间:
43+
44+
- `policy::type::handler` / `policy::type::handler_available`
45+
- `policy::concurrency::handler` / `policy::concurrency::injection`
46+
- `policy::value::handler` / `policy::value::decision`
47+
- `policy::error::handler` / `policy::error::request` / `policy::error::kind`
48+
49+
预设 policy 标签也按类别归档:
50+
51+
- `policy::value::{checked, unchecked, saturating}`
52+
- `policy::type::{strict, compatible, transparent}`
53+
- `policy::error::{throwing, expected, terminate}`
54+
- `policy::concurrency::{none, atomic}`
55+
56+
默认策略位于 `policy::defaults`:
57+
58+
- `policy::defaults::value`
59+
- `policy::defaults::type`
60+
- `policy::defaults::error`
61+
- `policy::defaults::concurrency`
62+
63+
4064
## 项目结构
4165
4266
```

examples/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
set(PRIMITIVES_EXAMPLE_SOURCES
2+
ex01_default_arithmetic.cpp
3+
ex02_type_policy.cpp
4+
ex03_value_policy.cpp
5+
ex04_error_policy.cpp
6+
ex05_concurrency_policy.cpp
7+
ex06_custom_underlying.cpp
8+
ex07_custom_policy.cpp
9+
ex08_custom_operation.cpp
10+
)
11+
12+
foreach(example_source IN LISTS PRIMITIVES_EXAMPLE_SOURCES)
13+
get_filename_component(example_name ${example_source} NAME_WE)
14+
add_executable(${example_name} ${example_source})
15+
target_link_libraries(${example_name} PRIVATE mcpplibs-primitives)
16+
endforeach()

examples/basic.cpp

Lines changed: 0 additions & 50 deletions
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <cstdint>
2+
#include <iostream>
3+
4+
import mcpplibs.primitives;
5+
6+
using namespace mcpplibs::primitives;
7+
8+
int main() {
9+
// Point 1: Use built-in primitive type aliases and framework operators.
10+
using namespace mcpplibs::primitives::types;
11+
using namespace mcpplibs::primitives::operators;
12+
13+
using value_t = I32<>;
14+
15+
// Prepare operands.
16+
auto const a = value_t{40};
17+
auto const b = value_t{2};
18+
19+
// Run the four arithmetic operators routed through dispatcher.
20+
auto const sum = a + b;
21+
auto const diff = a - b;
22+
auto const prod = a * b;
23+
auto const quot = a / b;
24+
25+
// Validate all dispatches succeeded.
26+
if (!sum.has_value() || !diff.has_value() || !prod.has_value() ||
27+
!quot.has_value()) {
28+
std::cerr << "default arithmetic failed\n";
29+
return 1;
30+
}
31+
32+
std::cout << "sum=" << sum->value() << ", diff=" << diff->value()
33+
<< ", prod=" << prod->value() << ", quot=" << quot->value() << '\n';
34+
return 0;
35+
}

0 commit comments

Comments
 (0)