1+ /*
2+ * Example: ex06_custom_underlying
3+ *
4+ * Purpose:
5+ * Demonstrate custom underlying integration, including rep bridge,
6+ * rep validation, and extensible common_rep negotiation.
7+ *
8+ * Expected results:
9+ * - UserInteger path succeeds and computes 40 + 2 = 42.
10+ * - NonNegativeInt path rejects invalid rep and returns domain_error.
11+ * - TaggedLhs/TaggedRhs path uses custom common_rep_traits to negotiate
12+ * TaggedCommonRep, then computes 40 + 2 = 42.
13+ * - Program prints a success message and exits with code 0.
14+ */
15+
116#include < iostream>
17+ #include < type_traits>
218
319import mcpplibs.primitives;
420
@@ -13,6 +29,110 @@ struct NonNegativeInt {
1329 int value;
1430};
1531
32+ struct TaggedLhs {
33+ int value;
34+
35+ friend constexpr auto operator +(TaggedLhs lhs, TaggedLhs rhs) noexcept
36+ -> TaggedLhs {
37+ return TaggedLhs{lhs.value + rhs.value };
38+ }
39+
40+ friend constexpr auto operator -(TaggedLhs lhs, TaggedLhs rhs) noexcept
41+ -> TaggedLhs {
42+ return TaggedLhs{lhs.value - rhs.value };
43+ }
44+
45+ friend constexpr auto operator *(TaggedLhs lhs, TaggedLhs rhs) noexcept
46+ -> TaggedLhs {
47+ return TaggedLhs{lhs.value * rhs.value };
48+ }
49+
50+ friend constexpr auto operator /(TaggedLhs lhs, TaggedLhs rhs) noexcept
51+ -> TaggedLhs {
52+ return TaggedLhs{lhs.value / rhs.value };
53+ }
54+
55+ friend constexpr auto operator ==(TaggedLhs lhs, TaggedLhs rhs) noexcept
56+ -> bool {
57+ return lhs.value == rhs.value ;
58+ }
59+
60+ constexpr explicit operator long long () const noexcept {
61+ return static_cast <long long >(value);
62+ }
63+ };
64+
65+ struct TaggedRhs {
66+ int value;
67+
68+ friend constexpr auto operator +(TaggedRhs lhs, TaggedRhs rhs) noexcept
69+ -> TaggedRhs {
70+ return TaggedRhs{lhs.value + rhs.value };
71+ }
72+
73+ friend constexpr auto operator -(TaggedRhs lhs, TaggedRhs rhs) noexcept
74+ -> TaggedRhs {
75+ return TaggedRhs{lhs.value - rhs.value };
76+ }
77+
78+ friend constexpr auto operator *(TaggedRhs lhs, TaggedRhs rhs) noexcept
79+ -> TaggedRhs {
80+ return TaggedRhs{lhs.value * rhs.value };
81+ }
82+
83+ friend constexpr auto operator /(TaggedRhs lhs, TaggedRhs rhs) noexcept
84+ -> TaggedRhs {
85+ return TaggedRhs{lhs.value / rhs.value };
86+ }
87+
88+ friend constexpr auto operator ==(TaggedRhs lhs, TaggedRhs rhs) noexcept
89+ -> bool {
90+ return lhs.value == rhs.value ;
91+ }
92+
93+ constexpr explicit operator long long () const noexcept {
94+ return static_cast <long long >(value);
95+ }
96+ };
97+
98+ struct TaggedCommonRep {
99+ long long value;
100+
101+ constexpr TaggedCommonRep () noexcept = default;
102+ constexpr explicit TaggedCommonRep (long long v) noexcept : value(v) {}
103+ constexpr explicit TaggedCommonRep (TaggedLhs v) noexcept : value(v.value) {}
104+ constexpr explicit TaggedCommonRep (TaggedRhs v) noexcept : value(v.value) {}
105+
106+ friend constexpr auto operator +(TaggedCommonRep lhs,
107+ TaggedCommonRep rhs) noexcept
108+ -> TaggedCommonRep {
109+ return TaggedCommonRep{lhs.value + rhs.value };
110+ }
111+
112+ friend constexpr auto operator -(TaggedCommonRep lhs,
113+ TaggedCommonRep rhs) noexcept
114+ -> TaggedCommonRep {
115+ return TaggedCommonRep{lhs.value - rhs.value };
116+ }
117+
118+ friend constexpr auto operator *(TaggedCommonRep lhs,
119+ TaggedCommonRep rhs) noexcept
120+ -> TaggedCommonRep {
121+ return TaggedCommonRep{lhs.value * rhs.value };
122+ }
123+
124+ friend constexpr auto operator /(TaggedCommonRep lhs,
125+ TaggedCommonRep rhs) noexcept
126+ -> TaggedCommonRep {
127+ return TaggedCommonRep{lhs.value / rhs.value };
128+ }
129+
130+ friend constexpr auto operator ==(TaggedCommonRep lhs,
131+ TaggedCommonRep rhs) noexcept -> bool {
132+ return lhs.value == rhs.value ;
133+ }
134+ };
135+
16136// Point 6 / Step 2: Register underlying::traits for UserInteger.
17137// This type has a full int bridge and accepts all reps.
18138template <> struct mcpplibs ::primitives::underlying::traits<UserInteger> {
@@ -55,6 +175,74 @@ template <> struct mcpplibs::primitives::underlying::traits<NonNegativeInt> {
55175 }
56176};
57177
178+ template <> struct mcpplibs ::primitives::underlying::traits<TaggedLhs> {
179+ using value_type = TaggedLhs;
180+ using rep_type = TaggedLhs;
181+
182+ static constexpr bool enabled = true ;
183+ static constexpr auto kind = category::integer;
184+
185+ static constexpr auto to_rep (value_type value) noexcept -> rep_type {
186+ return value;
187+ }
188+
189+ static constexpr auto from_rep (rep_type value) noexcept -> value_type {
190+ return value;
191+ }
192+
193+ static constexpr auto is_valid_rep (rep_type) noexcept -> bool { return true ; }
194+ };
195+
196+ template <> struct mcpplibs ::primitives::underlying::traits<TaggedRhs> {
197+ using value_type = TaggedRhs;
198+ using rep_type = TaggedRhs;
199+
200+ static constexpr bool enabled = true ;
201+ static constexpr auto kind = category::integer;
202+
203+ static constexpr auto to_rep (value_type value) noexcept -> rep_type {
204+ return value;
205+ }
206+
207+ static constexpr auto from_rep (rep_type value) noexcept -> value_type {
208+ return value;
209+ }
210+
211+ static constexpr auto is_valid_rep (rep_type) noexcept -> bool { return true ; }
212+ };
213+
214+ template <> struct mcpplibs ::primitives::underlying::traits<TaggedCommonRep> {
215+ using value_type = TaggedCommonRep;
216+ using rep_type = TaggedCommonRep;
217+
218+ static constexpr bool enabled = true ;
219+ static constexpr auto kind = category::integer;
220+
221+ static constexpr auto to_rep (value_type value) noexcept -> rep_type {
222+ return value;
223+ }
224+
225+ static constexpr auto from_rep (rep_type value) noexcept -> value_type {
226+ return value;
227+ }
228+
229+ static constexpr auto is_valid_rep (rep_type) noexcept -> bool { return true ; }
230+ };
231+
232+ template <>
233+ struct mcpplibs ::primitives::underlying::common_rep_traits<TaggedLhs,
234+ TaggedRhs> {
235+ using type = TaggedCommonRep;
236+ static constexpr bool enabled = true ;
237+ };
238+
239+ template <>
240+ struct mcpplibs ::primitives::underlying::common_rep_traits<TaggedRhs,
241+ TaggedLhs> {
242+ using type = TaggedCommonRep;
243+ static constexpr bool enabled = true ;
244+ };
245+
58246int main () {
59247 // Point 6 / Step 4A: Call operations on UserInteger custom underlying.
60248 using user_t =
@@ -81,6 +269,27 @@ int main() {
81269 return 1 ;
82270 }
83271
272+ // Point 6 / Step 4C: Demonstrate extensible common_rep negotiation.
273+ using lhs_t = primitive<TaggedLhs, policy::value::checked,
274+ policy::type::transparent, policy::error::expected>;
275+ using rhs_t = primitive<TaggedRhs, policy::value::checked,
276+ policy::type::transparent, policy::error::expected>;
277+
278+ using transparent_handler =
279+ policy::type::handler<policy::type::transparent, operations::Addition,
280+ TaggedLhs, TaggedRhs>;
281+ static_assert (transparent_handler::allowed);
282+ static_assert (
283+ std::same_as<typename transparent_handler::common_rep, TaggedCommonRep>);
284+
285+ auto const lhs = lhs_t {TaggedLhs{40 }};
286+ auto const rhs = rhs_t {TaggedRhs{2 }};
287+ auto const mixed_result = operations::add (lhs, rhs);
288+ if (!mixed_result.has_value () || mixed_result->value ().value != 42 ) {
289+ std::cerr << " custom common_rep negotiation failed\n " ;
290+ return 1 ;
291+ }
292+
84293 std::cout << " custom underlying demo passed\n " ;
85294 return 0 ;
86295}
0 commit comments