Skip to content

Commit b8cd620

Browse files
refactor: Adjust module struct for adding common_policies_t
1 parent 17fd977 commit b8cd620

File tree

2 files changed

+110
-23
lines changed

2 files changed

+110
-23
lines changed

src/policy/impl.cppm

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,6 @@ import mcpplibs.primitives.policy.traits;
66

77
export namespace mcpplibs::primitives::policy {
88

9-
struct checked_value {};
10-
struct unchecked_value {};
11-
struct saturating_value {};
12-
13-
struct strict_type {};
14-
struct category_compatible_type {};
15-
struct transparent_type {};
16-
17-
struct throw_error {};
18-
struct expected_error {};
19-
struct terminate_error {};
20-
21-
struct single_thread {};
22-
struct atomic {};
23-
249
template <> struct traits<checked_value> {
2510
using policy_type = checked_value;
2611
static constexpr bool enabled = true;
@@ -103,12 +88,4 @@ template <typename P>
10388
concept concurrency_policy =
10489
policy_type<P> && (traits<P>::kind == category::concurrency);
10590

106-
using default_value = checked_value;
107-
108-
using default_type = strict_type;
109-
110-
using default_error = throw_error;
111-
112-
using default_concurrency = single_thread;
113-
11491
} // namespace mcpplibs::primitives::policy

src/policy/traits.cppm

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
module;
2+
#include <tuple>
3+
#include <type_traits>
24

35
export module mcpplibs.primitives.policy.traits;
46

@@ -9,10 +11,118 @@ export namespace mcpplibs::primitives::policy {
911

1012
enum class category { value, type, error, concurrency };
1113

14+
// Built-in policy tags (defined here so `common_policies` can live in traits).
15+
struct checked_value {};
16+
struct unchecked_value {};
17+
struct saturating_value {};
18+
19+
struct strict_type {};
20+
struct category_compatible_type {};
21+
struct transparent_type {};
22+
23+
struct throw_error {};
24+
struct expected_error {};
25+
struct terminate_error {};
26+
27+
struct single_thread {};
28+
struct atomic {};
29+
1230
template <typename P> struct traits {
1331
using policy_type = void;
1432
static constexpr bool enabled = false;
1533
static constexpr auto kind = static_cast<category>(-1);
1634
};
1735

36+
// Customizable priority hooks — users can specialize these templates to
37+
// change how the library decides which policy wins when multiple are
38+
// provided. Specializations live in implementation or user code.
39+
template <typename = void> struct priority_value {
40+
using type = std::tuple<>;
41+
};
42+
template <typename = void> struct priority_type {
43+
using type = std::tuple<>;
44+
};
45+
template <typename = void> struct priority_error {
46+
using type = std::tuple<>;
47+
};
48+
template <typename = void> struct priority_concurrency {
49+
using type = std::tuple<>;
50+
};
51+
52+
// Library default priority ordering for built-in tags. Users can specialize
53+
// these hooks in their own code to change global priority ordering.
54+
template <> struct priority_value<void> {
55+
using type = std::tuple<checked_value, saturating_value, unchecked_value>;
56+
};
57+
58+
template <> struct priority_type<void> {
59+
using type =
60+
std::tuple<strict_type, category_compatible_type, transparent_type>;
61+
};
62+
63+
template <> struct priority_error<void> {
64+
using type = std::tuple<throw_error, expected_error, terminate_error>;
65+
};
66+
67+
template <> struct priority_concurrency<void> {
68+
using type = std::tuple<atomic, single_thread>;
69+
};
70+
71+
// Default hooks for library defaults. Implementations should specialize
72+
// these in the implementation submodule to bind to concrete tags.
73+
// Library defaults (built-in tags).
74+
using default_value = checked_value;
75+
using default_type = strict_type;
76+
using default_error = throw_error;
77+
using default_concurrency = single_thread;
78+
79+
// Internal helpers used by the merging algorithm.
80+
namespace details {
81+
template <typename T, typename... Ts> struct contains : std::false_type {};
82+
template <typename T, typename Head, typename... Tail>
83+
struct contains<T, Head, Tail...>
84+
: std::conditional_t<std::is_same_v<T, Head>, std::true_type,
85+
contains<T, Tail...>> {};
86+
87+
template <typename Default, typename PriorityTuple, typename... Ps>
88+
struct pick_first_from_priority_impl;
89+
90+
template <typename Default, typename FirstPriority, typename... RestPriorities,
91+
typename... Ps>
92+
struct pick_first_from_priority_impl<
93+
Default, std::tuple<FirstPriority, RestPriorities...>, Ps...> {
94+
using type = std::conditional_t<
95+
contains<FirstPriority, Ps...>::value, FirstPriority,
96+
typename pick_first_from_priority_impl<
97+
Default, std::tuple<RestPriorities...>, Ps...>::type>;
98+
};
99+
100+
template <typename Default, typename... Ps>
101+
struct pick_first_from_priority_impl<Default, std::tuple<>, Ps...> {
102+
using type = Default;
103+
};
104+
105+
} // namespace details
106+
107+
// Primary merging metafunction. Consumers can use `common_policies_t<...>`.
108+
template <typename... Ps> struct common_policies {
109+
using value_policy = details::pick_first_from_priority_impl<
110+
default_value, priority_value<>::type, Ps...>::type;
111+
112+
using type_policy = details::pick_first_from_priority_impl<
113+
default_type, priority_type<>::type, Ps...>::type;
114+
115+
using error_policy = details::pick_first_from_priority_impl<
116+
default_error, priority_error<>::type, Ps...>::type;
117+
118+
using concurrency_policy = details::pick_first_from_priority_impl<
119+
default_concurrency, priority_concurrency<>::type, Ps...>::type;
120+
121+
using type =
122+
std::tuple<value_policy, type_policy, error_policy, concurrency_policy>;
123+
};
124+
125+
template <typename... Ps>
126+
using common_policies_t = common_policies<Ps...>::type;
127+
18128
} // namespace mcpplibs::primitives::policy

0 commit comments

Comments
 (0)