11module ;
2+ #include < tuple>
3+ #include < type_traits>
24
35export module mcpplibs.primitives.policy.traits;
46
@@ -9,10 +11,118 @@ export namespace mcpplibs::primitives::policy {
911
1012enum 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+
1230template <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