@@ -23,6 +23,58 @@ template <typename DestRep, typename SrcRep>
2323concept builtin_numeric_pair =
2424 std_numeric<DestRep> && std_numeric<SrcRep>;
2525
26+ template <underlying_type T>
27+ using underlying_rep_t = underlying::traits<std::remove_cv_t <T>>::rep_type;
28+
29+ template <typename Rep, typename Candidate>
30+ concept builtin_numeric_proxy_candidate =
31+ std_numeric<Candidate> && has_common_rep<Rep, Candidate> &&
32+ !std::same_as<common_rep_t <Rep, Candidate>, void > &&
33+ std::same_as<common_rep_t <Rep, Candidate>, std::remove_cv_t <Candidate>> &&
34+ statically_castable<Candidate, Rep>;
35+
36+ template <typename Rep>
37+ struct integer_builtin_proxy {
38+ using type = std::conditional_t <
39+ builtin_numeric_proxy_candidate<Rep, short >, short ,
40+ std::conditional_t <
41+ builtin_numeric_proxy_candidate<Rep, unsigned short >, unsigned short ,
42+ std::conditional_t <
43+ builtin_numeric_proxy_candidate<Rep, int >, int ,
44+ std::conditional_t <
45+ builtin_numeric_proxy_candidate<Rep, unsigned int >,
46+ unsigned int ,
47+ std::conditional_t <
48+ builtin_numeric_proxy_candidate<Rep, long >, long ,
49+ std::conditional_t <
50+ builtin_numeric_proxy_candidate<Rep, unsigned long >,
51+ unsigned long ,
52+ std::conditional_t <
53+ builtin_numeric_proxy_candidate<Rep, long long >,
54+ long long ,
55+ std::conditional_t <
56+ builtin_numeric_proxy_candidate<
57+ Rep, unsigned long long >,
58+ unsigned long long , void >>>>>>>>;
59+ };
60+
61+ template <typename Rep>
62+ using integer_builtin_proxy_t = integer_builtin_proxy<Rep>::type;
63+
64+ template <typename Rep>
65+ struct floating_builtin_proxy {
66+ using type = std::conditional_t <
67+ builtin_numeric_proxy_candidate<Rep, float >, float ,
68+ std::conditional_t <
69+ builtin_numeric_proxy_candidate<Rep, double >, double ,
70+ std::conditional_t <
71+ builtin_numeric_proxy_candidate<Rep, long double >, long double ,
72+ void >>>;
73+ };
74+
75+ template <typename Rep>
76+ using floating_builtin_proxy_t = floating_builtin_proxy<Rep>::type;
77+
2678template <std_integer DestRep, std_integer SrcRep>
2779constexpr auto numeric_risk (SrcRep value)
2880 -> std::optional<risk::kind> {
@@ -145,6 +197,32 @@ constexpr auto numeric_risk(SrcRep value)
145197 return std::nullopt ;
146198}
147199
200+ template <numeric_underlying_type Dest, numeric_underlying_type Src>
201+ constexpr auto numeric_underlying_risk (Src value)
202+ -> std::optional<risk::kind> {
203+ using src_type = std::remove_cv_t <Src>;
204+ using dest_type = std::remove_cv_t <Dest>;
205+ using src_rep_type = underlying_rep_t <src_type>;
206+ using dest_rep_type = underlying_rep_t <dest_type>;
207+ using src_builtin_rep_type = std::conditional_t <
208+ integer_underlying_type<src_type>, integer_builtin_proxy_t <src_rep_type>,
209+ floating_builtin_proxy_t <src_rep_type>>;
210+ using dest_builtin_rep_type = std::conditional_t <
211+ integer_underlying_type<dest_type>,
212+ integer_builtin_proxy_t <dest_rep_type>,
213+ floating_builtin_proxy_t <dest_rep_type>>;
214+
215+ if constexpr (std::same_as<src_builtin_rep_type, void > ||
216+ std::same_as<dest_builtin_rep_type, void >) {
217+ static_cast <void >(value);
218+ return risk::kind::invalid_type_combination;
219+ } else {
220+ auto const source_rep = underlying::traits<src_type>::to_rep (value);
221+ return numeric_risk<dest_builtin_rep_type>(
222+ static_cast <src_builtin_rep_type>(source_rep));
223+ }
224+ }
225+
148226template <numeric_underlying_type DestRep, numeric_underlying_type SrcRep>
149227 requires statically_castable<DestRep, SrcRep>
150228constexpr auto unchecked_rep_cast (SrcRep value) noexcept
@@ -279,28 +357,28 @@ constexpr auto cast_underlying_result(Src value, RepCaster rep_caster)
279357
280358export namespace mcpplibs ::primitives::conversion {
281359
282- template <std_integer DestRep, std_integer SrcRep>
360+ template <integer_underlying_type DestRep, integer_underlying_type SrcRep>
283361constexpr auto numeric_risk (SrcRep value)
284362 -> std::optional<risk::kind> {
285- return details::numeric_risk <DestRep>(value);
363+ return details::numeric_underlying_risk <DestRep>(value);
286364}
287365
288- template <std_integer DestRep, std_floating SrcRep>
366+ template <integer_underlying_type DestRep, floating_underlying_type SrcRep>
289367constexpr auto numeric_risk (SrcRep value)
290368 -> std::optional<risk::kind> {
291- return details::numeric_risk <DestRep>(value);
369+ return details::numeric_underlying_risk <DestRep>(value);
292370}
293371
294- template <std_floating DestRep, std_integer SrcRep>
372+ template <floating_underlying_type DestRep, integer_underlying_type SrcRep>
295373constexpr auto numeric_risk (SrcRep value)
296374 -> std::optional<risk::kind> {
297- return details::numeric_risk <DestRep>(value);
375+ return details::numeric_underlying_risk <DestRep>(value);
298376}
299377
300- template <std_floating DestRep, std_floating SrcRep>
378+ template <floating_underlying_type DestRep, floating_underlying_type SrcRep>
301379constexpr auto numeric_risk (SrcRep value)
302380 -> std::optional<risk::kind> {
303- return details::numeric_risk <DestRep>(value);
381+ return details::numeric_underlying_risk <DestRep>(value);
304382}
305383
306384template <underlying_type Dest, underlying_type Src>
0 commit comments