Skip to content

Commit 4d8e457

Browse files
docs: point default policy aliases to mcpplibs::primitives and update examples
1 parent ccd5896 commit 4d8e457

File tree

10 files changed

+227
-25
lines changed

10 files changed

+227
-25
lines changed

.agents/docs/RFC.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,23 @@
4444
4. 零开销抽象,未启用策略不额外付费,`constexpr`友好。
4545
5. 允许渐进迁移。
4646

47-
## 安全策略体系提案
47+
## 安全策略体系
4848

4949
### 值安全
5050

5151
- `checked_value`(默认)
5252
- `unchecked_value`
5353
- `saturating_value`
5454

55-
关注点:和底层类型的互转、构造,底层类型值域限制,算术/比较的溢出/下溢/除零行为。
55+
关注点:`underlying_type` 值域限制,算术/比较的溢出/下溢/除零行为。
5656

5757
### 类型安全
5858

59-
- `strict_type`(默认)
60-
- `relaxed_type`
59+
- `strict_type`
60+
- `category_compatible_type`
61+
- `transparent_type`(原 `relaxed_type`,最宽松)
6162

62-
关注点:primitive 之间的隐式/显式转换规则,是否允许跨类型算术(如 `Integer + Floating`)或比较。
63+
关注点:`primitive` 之间/ `primitive``underlying_type` 的隐式/显式转换规则,是否允许跨类型算术(如 `Integer + Floating`)或比较。
6364

6465
### 错误模型 / 异常安全
6566

.agents/docs/architecture.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,8 @@ ctest --test-dir build
137137

138138
项目中新增了 `mcpplibs::primitive::policy` 模块,用来表达运行时/编译期的策略标签。核心要点:
139139

140-
- `policy::category`:一个枚举,用以表示四类策略:`value``type``error``concurrency`
141-
- 每个 policy 类型匹配一个 `policy::traits<P>` 特化,`traits` 提供 `enabled``kind`(category)。
142-
- 提供了 `policy::policy_type<P>` 概念用于识别有效的 policy 类型。
143-
- `policy::default_policies` 提供库的默认策略集合(`value`, `type`, `error`, `concurrency`)。
140+
库默认策略别名由 `mcpplibs::primitives` 导出:`default_value_policy`, `default_type_policy`, `default_error_policy`, `default_concurrency_policy`
141+
144142

145143
示例用法见 [examples/basic.cpp](examples/basic.cpp#L1)(演示如何查询默认策略与内建策略的类别)。
146144

@@ -155,7 +153,7 @@ ctest --test-dir build
155153
- 策略传播:添加 `traits/primitive_traits.cppm`,提供 `primitive_traits<Primitive>`,包含:
156154
- `using value_type` — 底层类型
157155
- `using policies = std::tuple<...>` — 策略标签元组
158-
- `using default_policies = policy::default_policies`
156+
- 默认策略别名可通过 `mcpplibs::primitives::default_*_policy` 访问(例如 `default_value_policy`)。
159157
- 编译期谓词 `has_policy_category<Primitive, policy::category::value>` 等,便于操作 trait 的约束和重载。
160158
- 可扩展性:`primitive` 的操作(例如算术、比较)将通过独立的 operation traits 和 concepts 实现,使用 `primitive_traits` 中的 policy 信息进行选择。
161159

.vscode/compile_commands.json

Whitespace-only changes.

examples/basic.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ int main() {
1212
std::cout << "double is std_floating: " << std_floating<double> << "\n";
1313
std::cout << "int is underlying_type: " << underlying_type<int> << "\n";
1414

15-
std::cout << "default value policy is unchecked_value: "
16-
<< std::is_same_v<policy::default_policies::value,
17-
policy::unchecked_value> << "\n";
15+
std::cout
16+
<< "default value policy is unchecked_value: "
17+
<< std::is_same_v<::mcpplibs::primitives::default_value_policy,
18+
::mcpplibs::primitive::policy::unchecked_value> << "\n";
1819

1920
std::cout << "checked_value is a policy_type: "
2021
<< policy_type<checked_value> << "\n";

src/primitives/primitive.cppm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module;
2+
export module mcpplibs.primitives.primitive;
3+
4+
export import mcpplibs.primitives.primitive.traits;
5+
export import mcpplibs.primitives.primitive.impl;

src/primitives/primitive.impl.cppm

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module;
2+
#include <tuple>
3+
4+
export module mcpplibs.primitives.primitive.impl;
5+
6+
// Import policy concept to constrain Policies parameter pack.
7+
export import mcpplibs.primitive.traits.policy;
8+
9+
export namespace mcpplibs::primitives {
10+
11+
template <typename T, primitive::policy::policy_type... Policies>
12+
struct primitive {
13+
using value_type = T;
14+
using policies = std::tuple<Policies...>;
15+
constexpr explicit primitive(T v) noexcept : value(v) {}
16+
T value;
17+
};
18+
19+
} // namespace mcpplibs::primitives
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
module;
2+
#include <tuple>
3+
#include <type_traits>
4+
5+
export module mcpplibs.primitives.primitive.traits;
6+
7+
// Import the policy taxonomy so we can inspect policy::traits<>.
8+
export import mcpplibs.primitive.traits.policy;
9+
10+
// Public default policy aliases — these must be visible to internal details.
11+
export namespace mcpplibs::primitives {
12+
using default_value_policy = ::mcpplibs::primitive::policy::unchecked_value;
13+
using default_type_policy = ::mcpplibs::primitive::policy::transparent_type;
14+
using default_error_policy = ::mcpplibs::primitive::policy::throw_error;
15+
using default_concurrency_policy = ::mcpplibs::primitive::policy::single_thread;
16+
}
17+
18+
// Internal implementation details — not exported.
19+
namespace mcpplibs::primitives::traits::details {
20+
using policy_category = ::mcpplibs::primitive::policy::category;
21+
22+
template <policy_category C,
23+
::mcpplibs::primitive::policy::policy_type... Policies>
24+
struct count_matching_impl;
25+
26+
template <policy_category C> struct count_matching_impl<C> {
27+
static constexpr std::size_t value = 0;
28+
};
29+
30+
template <policy_category C, ::mcpplibs::primitive::policy::policy_type First,
31+
::mcpplibs::primitive::policy::policy_type... Rest>
32+
struct count_matching_impl<C, First, Rest...> {
33+
static constexpr std::size_t rest = count_matching_impl<C, Rest...>::value;
34+
static constexpr bool is_match =
35+
::mcpplibs::primitive::policy::traits<First>::enabled &&
36+
(::mcpplibs::primitive::policy::traits<First>::kind == C);
37+
static constexpr std::size_t value = rest + (is_match ? 1u : 0u);
38+
};
39+
40+
template <policy_category C,
41+
::mcpplibs::primitive::policy::policy_type... Policies>
42+
constexpr std::size_t count_matching_v =
43+
count_matching_impl<C, Policies...>::value;
44+
45+
template <policy_category C,
46+
::mcpplibs::primitive::policy::policy_type... Policies>
47+
struct find_first_impl;
48+
49+
template <policy_category C> struct find_first_impl<C> {
50+
using type = void;
51+
};
52+
53+
template <policy_category C, ::mcpplibs::primitive::policy::policy_type First,
54+
::mcpplibs::primitive::policy::policy_type... Rest>
55+
struct find_first_impl<C, First, Rest...> {
56+
static constexpr bool is_match =
57+
::mcpplibs::primitive::policy::traits<First>::enabled &&
58+
(::mcpplibs::primitive::policy::traits<First>::kind == C);
59+
using type = std::conditional_t<is_match, First,
60+
typename find_first_impl<C, Rest...>::type>;
61+
};
62+
63+
template <policy_category C, primitive::policy::policy_type... Policies>
64+
using find_first_t = find_first_impl<C, Policies...>::type;
65+
66+
template <policy_category C, primitive::policy::policy_type... Policies>
67+
struct resolve_policy_impl {
68+
static_assert(count_matching_v<C, Policies...> <= 1,
69+
"Multiple policies provided for the same category");
70+
71+
using found = find_first_t<C, Policies...>;
72+
using type = std::conditional_t<
73+
std::is_same_v<found, void>,
74+
std::conditional_t<
75+
C == policy_category::value, primitives::default_value_policy,
76+
std::conditional_t<
77+
C == policy_category::type, primitives::default_type_policy,
78+
std::conditional_t<C == policy_category::error,
79+
primitives::default_error_policy,
80+
primitives::default_concurrency_policy>>>,
81+
found>;
82+
};
83+
84+
template <policy_category C,
85+
::mcpplibs::primitive::policy::policy_type... Policies>
86+
using resolve_policy_t = typename resolve_policy_impl<C, Policies...>::type;
87+
88+
} // namespace mcpplibs::primitives::traits::details
89+
90+
// Public API exported from this module.
91+
export namespace mcpplibs::primitives::traits {
92+
using policy_category = ::mcpplibs::primitive::policy::category;
93+
94+
template <policy_category C,
95+
::mcpplibs::primitive::policy::policy_type... Policies>
96+
using resolve_policy_t =
97+
::mcpplibs::primitives::traits::details::resolve_policy_t<C, Policies...>;
98+
99+
template <typename P> struct primitive_traits; // customization point for users
100+
101+
// Forward-declare exported `primitive` (defined in impl module).
102+
template <typename T, ::mcpplibs::primitive::policy::policy_type... Policies>
103+
struct primitive;
104+
105+
template <typename T, ::mcpplibs::primitive::policy::policy_type... Policies>
106+
struct primitive_traits<primitive<T, Policies...>> {
107+
using value_type = T;
108+
using policies = std::tuple<Policies...>;
109+
using value_policy = resolve_policy_t<policy_category::value, Policies...>;
110+
using type_policy = resolve_policy_t<policy_category::type, Policies...>;
111+
using error_policy = resolve_policy_t<policy_category::error, Policies...>;
112+
using concurrency_policy =
113+
resolve_policy_t<policy_category::concurrency, Policies...>;
114+
};
115+
116+
} // namespace traits::traits
117+

src/traits/policy.cppm

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,71 +10,107 @@ namespace policy {
1010
enum class category { value, type, error, concurrency };
1111

1212
template <typename P> struct traits {
13+
using policy_type = void;
1314
static constexpr bool enabled = false;
1415
static constexpr category kind = static_cast<category>(-1);
1516
};
1617

1718
struct checked_value {};
1819
struct unchecked_value {};
20+
struct saturating_value {};
1921

2022
struct strict_type {};
21-
struct relaxed_type {};
23+
struct category_compatible_type {};
24+
struct transparent_type {};
2225

2326
struct throw_error {};
2427
struct expected_error {};
28+
struct terminate_error {};
2529

2630
struct single_thread {};
2731
struct atomic {};
2832

2933
template <> struct traits<checked_value> {
34+
using policy_type = checked_value;
3035
static constexpr bool enabled = true;
3136
static constexpr category kind = category::value;
3237
};
3338

3439
template <> struct traits<unchecked_value> {
40+
using policy_type = unchecked_value;
41+
static constexpr bool enabled = true;
42+
static constexpr category kind = category::value;
43+
};
44+
45+
template <> struct traits<saturating_value> {
46+
using policy_type = saturating_value;
3547
static constexpr bool enabled = true;
3648
static constexpr category kind = category::value;
3749
};
3850

3951
template <> struct traits<strict_type> {
52+
using policy_type = strict_type;
53+
static constexpr bool enabled = true;
54+
static constexpr category kind = category::type;
55+
};
56+
57+
template <> struct traits<category_compatible_type> {
58+
using policy_type = category_compatible_type;
4059
static constexpr bool enabled = true;
4160
static constexpr category kind = category::type;
4261
};
4362

44-
template <> struct traits<relaxed_type> {
63+
template <> struct traits<transparent_type> {
64+
using policy_type = transparent_type;
4565
static constexpr bool enabled = true;
4666
static constexpr category kind = category::type;
4767
};
4868

4969
template <> struct traits<throw_error> {
70+
using policy_type = throw_error;
5071
static constexpr bool enabled = true;
5172
static constexpr category kind = category::error;
5273
};
5374

5475
template <> struct traits<expected_error> {
76+
using policy_type = expected_error;
77+
static constexpr bool enabled = true;
78+
static constexpr category kind = category::error;
79+
};
80+
81+
template <> struct traits<terminate_error> {
82+
using policy_type = terminate_error;
5583
static constexpr bool enabled = true;
5684
static constexpr category kind = category::error;
5785
};
5886

5987
template <> struct traits<single_thread> {
88+
using policy_type = single_thread;
6089
static constexpr bool enabled = true;
6190
static constexpr category kind = category::concurrency;
6291
};
6392

6493
template <> struct traits<atomic> {
94+
using policy_type = atomic;
6595
static constexpr bool enabled = true;
6696
static constexpr category kind = category::concurrency;
6797
};
6898

6999
template <typename P>
70100
concept policy_type = traits<P>::enabled;
71101

72-
struct default_policies {
73-
using value = unchecked_value;
74-
using type = relaxed_type;
75-
using error = throw_error;
76-
using concurrency = single_thread;
77-
};
102+
template <typename P>
103+
concept value_policy = policy_type<P> && (traits<P>::kind == category::value);
104+
105+
template <typename P>
106+
concept type_policy = policy_type<P> && (traits<P>::kind == category::type);
107+
108+
template <typename P>
109+
concept error_policy = policy_type<P> && (traits<P>::kind == category::error);
110+
111+
template <typename P>
112+
concept concurrency_policy =
113+
policy_type<P> && (traits<P>::kind == category::concurrency);
78114

79115
} // namespace policy
80116

src/traits/traits.cppm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,11 @@ export module mcpplibs.primitive.traits;
44

55
export import mcpplibs.primitive.traits.underlying;
66
export import mcpplibs.primitive.traits.policy;
7+
8+
// Expose default policy aliases from the primitives-facing traits module.
9+
export namespace mcpplibs::primitives {
10+
using default_value_policy = ::mcpplibs::primitive::policy::unchecked_value;
11+
using default_type_policy = ::mcpplibs::primitive::policy::transparent_type;
12+
using default_error_policy = ::mcpplibs::primitive::policy::throw_error;
13+
using default_concurrency_policy = ::mcpplibs::primitive::policy::single_thread;
14+
} // namespace mcpplibs::primitives

tests/basic/test_policies.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,38 @@ TEST(PolicyTraitsTest, BuiltinPoliciesHaveCategories) {
1313
EXPECT_EQ(policy::traits<policy::checked_value>::kind,
1414
policy::category::value);
1515

16-
EXPECT_TRUE((policy::traits<policy::relaxed_type>::enabled));
17-
EXPECT_EQ(policy::traits<policy::relaxed_type>::kind, policy::category::type);
16+
EXPECT_TRUE((policy::traits<policy::category_compatible_type>::enabled));
17+
EXPECT_EQ(policy::traits<policy::category_compatible_type>::kind,
18+
policy::category::type);
19+
20+
EXPECT_TRUE((policy::traits<policy::transparent_type>::enabled));
21+
EXPECT_EQ(policy::traits<policy::transparent_type>::kind,
22+
policy::category::type);
1823

1924
EXPECT_TRUE((policy::traits<policy::throw_error>::enabled));
2025
EXPECT_EQ(policy::traits<policy::throw_error>::kind, policy::category::error);
2126

27+
EXPECT_TRUE((policy::traits<policy::terminate_error>::enabled));
28+
EXPECT_EQ(policy::traits<policy::terminate_error>::kind,
29+
policy::category::error);
30+
2231
EXPECT_TRUE((policy::traits<policy::single_thread>::enabled));
2332
EXPECT_EQ(policy::traits<policy::single_thread>::kind,
2433
policy::category::concurrency);
2534

35+
EXPECT_TRUE((policy::traits<policy::saturating_value>::enabled));
36+
EXPECT_EQ(policy::traits<policy::saturating_value>::kind,
37+
policy::category::value);
38+
2639
EXPECT_TRUE((policy_type<policy::checked_value>));
40+
EXPECT_TRUE((policy_type<policy::terminate_error>));
2741
EXPECT_FALSE((policy_type<int>));
2842

29-
EXPECT_TRUE((std::is_same_v<policy::default_policies::value,
30-
policy::unchecked_value>));
43+
EXPECT_TRUE((std::is_same_v<::mcpplibs::primitives::default_value_policy,
44+
::mcpplibs::primitive::policy::unchecked_value>));
45+
EXPECT_TRUE(
46+
(std::is_same_v<::mcpplibs::primitives::default_type_policy,
47+
::mcpplibs::primitive::policy::transparent_type>));
3148
}
3249

3350
// Use the existing test runner main from other test translation unit.

0 commit comments

Comments
 (0)