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,55 @@ struct NonNegativeInt {
1329 int value;
1430};
1531
32+ struct TaggedLhs {
33+ int value;
34+
35+ constexpr explicit operator long long () const noexcept {
36+ return static_cast <long long >(value);
37+ }
38+ };
39+
40+ struct TaggedRhs {
41+ int value;
42+
43+ constexpr explicit operator long long () const noexcept {
44+ return static_cast <long long >(value);
45+ }
46+ };
47+
48+ struct TaggedCommonRep {
49+ long long value;
50+
51+ friend constexpr auto operator +(TaggedCommonRep lhs,
52+ TaggedCommonRep rhs) noexcept
53+ -> TaggedCommonRep {
54+ return TaggedCommonRep{lhs.value + rhs.value };
55+ }
56+
57+ friend constexpr auto operator -(TaggedCommonRep lhs,
58+ TaggedCommonRep rhs) noexcept
59+ -> TaggedCommonRep {
60+ return TaggedCommonRep{lhs.value - rhs.value };
61+ }
62+
63+ friend constexpr auto operator *(TaggedCommonRep lhs,
64+ TaggedCommonRep rhs) noexcept
65+ -> TaggedCommonRep {
66+ return TaggedCommonRep{lhs.value * rhs.value };
67+ }
68+
69+ friend constexpr auto operator /(TaggedCommonRep lhs,
70+ TaggedCommonRep rhs) noexcept
71+ -> TaggedCommonRep {
72+ return TaggedCommonRep{lhs.value / rhs.value };
73+ }
74+
75+ friend constexpr auto operator ==(TaggedCommonRep lhs,
76+ TaggedCommonRep rhs) noexcept -> bool {
77+ return lhs.value == rhs.value ;
78+ }
79+ };
80+
1681// Point 6 / Step 2: Register underlying::traits for UserInteger.
1782// This type has a full int bridge and accepts all reps.
1883template <> struct mcpplibs ::primitives::underlying::traits<UserInteger> {
@@ -55,6 +120,56 @@ template <> struct mcpplibs::primitives::underlying::traits<NonNegativeInt> {
55120 }
56121};
57122
123+ template <> struct mcpplibs ::primitives::underlying::traits<TaggedLhs> {
124+ using value_type = TaggedLhs;
125+ using rep_type = TaggedLhs;
126+
127+ static constexpr bool enabled = true ;
128+ static constexpr auto kind = category::integer;
129+
130+ static constexpr auto to_rep (value_type value) noexcept -> rep_type {
131+ return value;
132+ }
133+
134+ static constexpr auto from_rep (rep_type value) noexcept -> value_type {
135+ return value;
136+ }
137+
138+ static constexpr auto is_valid_rep (rep_type) noexcept -> bool { return true ; }
139+ };
140+
141+ template <> struct mcpplibs ::primitives::underlying::traits<TaggedRhs> {
142+ using value_type = TaggedRhs;
143+ using rep_type = TaggedRhs;
144+
145+ static constexpr bool enabled = true ;
146+ static constexpr auto kind = category::integer;
147+
148+ static constexpr auto to_rep (value_type value) noexcept -> rep_type {
149+ return value;
150+ }
151+
152+ static constexpr auto from_rep (rep_type value) noexcept -> value_type {
153+ return value;
154+ }
155+
156+ static constexpr auto is_valid_rep (rep_type) noexcept -> bool { return true ; }
157+ };
158+
159+ template <>
160+ struct mcpplibs ::primitives::underlying::common_rep_traits<TaggedLhs,
161+ TaggedRhs> {
162+ using type = TaggedCommonRep;
163+ static constexpr bool enabled = true ;
164+ };
165+
166+ template <>
167+ struct mcpplibs ::primitives::underlying::common_rep_traits<TaggedRhs,
168+ TaggedLhs> {
169+ using type = TaggedCommonRep;
170+ static constexpr bool enabled = true ;
171+ };
172+
58173int main () {
59174 // Point 6 / Step 4A: Call operations on UserInteger custom underlying.
60175 using user_t =
@@ -81,6 +196,27 @@ int main() {
81196 return 1 ;
82197 }
83198
199+ // Point 6 / Step 4C: Demonstrate extensible common_rep negotiation.
200+ using lhs_t = primitive<TaggedLhs, policy::value::checked,
201+ policy::type::transparent, policy::error::expected>;
202+ using rhs_t = primitive<TaggedRhs, policy::value::checked,
203+ policy::type::transparent, policy::error::expected>;
204+
205+ using transparent_handler =
206+ policy::type::handler<policy::type::transparent, operations::Addition,
207+ TaggedLhs, TaggedRhs>;
208+ static_assert (transparent_handler::allowed);
209+ static_assert (
210+ std::same_as<typename transparent_handler::common_rep, TaggedCommonRep>);
211+
212+ auto const lhs = lhs_t {TaggedLhs{40 }};
213+ auto const rhs = rhs_t {TaggedRhs{2 }};
214+ auto const mixed_result = operations::add (lhs, rhs);
215+ if (!mixed_result.has_value () || mixed_result->value ().value != 42 ) {
216+ std::cerr << " custom common_rep negotiation failed\n " ;
217+ return 1 ;
218+ }
219+
84220 std::cout << " custom underlying demo passed\n " ;
85221 return 0 ;
86222}
0 commit comments