Skip to content

Commit 2510fc1

Browse files
refactor: Introduce underlying proxy types for improved numeric type handling
Signed-off-by: FrozenlemonTee <1115306170@qq.com>
1 parent 66c758a commit 2510fc1

1 file changed

Lines changed: 86 additions & 8 deletions

File tree

src/conversion/underlying.cppm

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,58 @@ template <typename DestRep, typename SrcRep>
2323
concept 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+
2678
template <std_integer DestRep, std_integer SrcRep>
2779
constexpr 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+
148226
template <numeric_underlying_type DestRep, numeric_underlying_type SrcRep>
149227
requires statically_castable<DestRep, SrcRep>
150228
constexpr auto unchecked_rep_cast(SrcRep value) noexcept
@@ -279,28 +357,28 @@ constexpr auto cast_underlying_result(Src value, RepCaster rep_caster)
279357

280358
export namespace mcpplibs::primitives::conversion {
281359

282-
template <std_integer DestRep, std_integer SrcRep>
360+
template <integer_underlying_type DestRep, integer_underlying_type SrcRep>
283361
constexpr 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>
289367
constexpr 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>
295373
constexpr 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>
301379
constexpr 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

306384
template <underlying_type Dest, underlying_type Src>

0 commit comments

Comments
 (0)