Skip to content

Commit be07d3f

Browse files
refactor: Update conversion module imports and simplify casting logic for improved clarity to resolve #17 compile problem
1 parent 2452fba commit be07d3f

2 files changed

Lines changed: 14 additions & 197 deletions

File tree

src/operations/operators.cppm

Lines changed: 9 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
module;
22

3-
#include <cmath>
43
#include <compare>
54
#include <concepts>
6-
#include <cstdint>
75
#include <expected>
8-
#include <limits>
9-
#include <optional>
106
#include <type_traits>
117
#include <utility>
128

@@ -17,9 +13,11 @@ import mcpplibs.primitives.operations.dispatcher;
1713
import mcpplibs.primitives.operations.impl;
1814
import mcpplibs.primitives.primitive.impl;
1915
import mcpplibs.primitives.primitive.traits;
16+
import mcpplibs.primitives.conversion.traits;
17+
import mcpplibs.primitives.conversion.underlying;
2018
import mcpplibs.primitives.policy.handler;
2119
import mcpplibs.primitives.policy.impl;
22-
import mcpplibs.primitives.underlying;
20+
import mcpplibs.primitives.underlying.traits;
2321

2422

2523
namespace mcpplibs::primitives::operations::details {
@@ -62,128 +60,14 @@ constexpr auto decode_three_way_code(CommonRep const &code) -> Ordering {
6260
return Ordering::equivalent;
6361
}
6462

65-
enum class assign_risk : unsigned char {
66-
overflow,
67-
underflow,
68-
domain_error,
69-
precision_loss,
70-
};
71-
72-
template <typename DestRep, typename SrcRep>
73-
concept statically_castable = requires(SrcRep value) {
74-
static_cast<std::remove_cvref_t<DestRep>>(value);
75-
};
76-
77-
template <std_integer DestRep, std_integer SrcRep>
78-
constexpr auto numeric_risk(SrcRep value) -> std::optional<assign_risk> {
79-
using dest_type = std::remove_cvref_t<DestRep>;
80-
using src_type = std::remove_cvref_t<SrcRep>;
81-
82-
if constexpr (std::is_signed_v<src_type>) {
83-
auto const signed_value = static_cast<std::intmax_t>(value);
84-
if constexpr (std::is_signed_v<dest_type>) {
85-
if (signed_value <
86-
static_cast<std::intmax_t>(std::numeric_limits<dest_type>::min())) {
87-
return assign_risk::underflow;
88-
}
89-
if (signed_value >
90-
static_cast<std::intmax_t>(std::numeric_limits<dest_type>::max())) {
91-
return assign_risk::overflow;
92-
}
93-
} else {
94-
if (signed_value < 0) {
95-
return assign_risk::underflow;
96-
}
97-
if (static_cast<std::uintmax_t>(signed_value) >
98-
static_cast<std::uintmax_t>(std::numeric_limits<dest_type>::max())) {
99-
return assign_risk::overflow;
100-
}
101-
}
102-
} else {
103-
auto const unsigned_value = static_cast<std::uintmax_t>(value);
104-
if (unsigned_value >
105-
static_cast<std::uintmax_t>(std::numeric_limits<dest_type>::max())) {
106-
return assign_risk::overflow;
107-
}
108-
}
109-
110-
return std::nullopt;
111-
}
112-
113-
template <std_integer DestRep, std_floating SrcRep>
114-
constexpr auto numeric_risk(SrcRep value) -> std::optional<assign_risk> {
115-
using dest_type = std::remove_cvref_t<DestRep>;
116-
using src_type = std::remove_cvref_t<SrcRep>;
117-
118-
if (std::isnan(value)) {
119-
return assign_risk::domain_error;
120-
}
121-
if (std::isinf(value)) {
122-
return value < static_cast<src_type>(0) ? assign_risk::underflow
123-
: assign_risk::overflow;
124-
}
125-
126-
auto const normalized = static_cast<long double>(value);
127-
auto const min_value =
128-
static_cast<long double>(std::numeric_limits<dest_type>::lowest());
129-
auto const max_value =
130-
static_cast<long double>(std::numeric_limits<dest_type>::max());
131-
132-
if (normalized < min_value) {
133-
return assign_risk::underflow;
134-
}
135-
if (normalized > max_value) {
136-
return assign_risk::overflow;
137-
}
138-
return std::nullopt;
139-
}
140-
141-
template <typename DestRep, typename SrcRep>
142-
constexpr auto numeric_risk(SrcRep value) -> std::optional<assign_risk> {
143-
using dest_type = std::remove_cvref_t<DestRep>;
144-
using src_type = std::remove_cvref_t<SrcRep>;
145-
146-
if constexpr (std_integer<dest_type> && std_integer<src_type>) {
147-
return numeric_risk<dest_type, src_type>(value);
148-
} else if constexpr (std_integer<dest_type> && std_floating<src_type>) {
149-
return numeric_risk<dest_type, src_type>(value);
150-
} else {
151-
return std::nullopt;
152-
}
153-
}
154-
155-
template <typename DestRep, typename SrcRep>
156-
requires statically_castable<DestRep, SrcRep>
157-
constexpr auto saturating_rep_cast(SrcRep value) noexcept
158-
-> std::remove_cvref_t<DestRep> {
159-
using dest_type = std::remove_cvref_t<DestRep>;
160-
using src_type = std::remove_cvref_t<SrcRep>;
161-
162-
if constexpr (std_integer<dest_type> && std_numeric<src_type>) {
163-
if (auto const kind = numeric_risk<dest_type>(value); kind.has_value()) {
164-
if (*kind == assign_risk::overflow) {
165-
return std::numeric_limits<dest_type>::max();
166-
}
167-
if (*kind == assign_risk::underflow) {
168-
return std::numeric_limits<dest_type>::lowest();
169-
}
170-
if (*kind == assign_risk::domain_error) {
171-
return dest_type{};
172-
}
173-
}
174-
}
175-
176-
return static_cast<dest_type>(value);
177-
}
178-
179-
constexpr auto to_policy_error_kind(assign_risk kind)
63+
constexpr auto to_policy_error_kind(const conversion::risk::kind kind)
18064
-> policy::error::kind {
18165
switch (kind) {
182-
case assign_risk::overflow:
66+
case conversion::risk::kind::overflow:
18367
return policy::error::kind::overflow;
184-
case assign_risk::underflow:
68+
case conversion::risk::kind::underflow:
18569
return policy::error::kind::underflow;
186-
case assign_risk::domain_error:
70+
case conversion::risk::kind::domain_error:
18771
return policy::error::kind::domain_error;
18872
default:
18973
return policy::error::kind::unspecified;
@@ -663,7 +547,7 @@ constexpr auto apply_assign(Lhs &lhs, Rhs const &rhs)
663547
if constexpr (std::same_as<lhs_value_policy, policy::value::checked> &&
664548
std_integer<lhs_rep> && std_numeric<common_rep>) {
665549
if (auto const kind =
666-
details::numeric_risk<lhs_rep>(assigned_common_rep);
550+
conversion::numeric_risk<lhs_rep>(assigned_common_rep);
667551
kind.has_value()) {
668552
return std::unexpected(
669553
details::to_error_payload<ErrorPayload>(
@@ -672,7 +556,7 @@ constexpr auto apply_assign(Lhs &lhs, Rhs const &rhs)
672556
}
673557

674558
auto const assigned_rep =
675-
details::saturating_rep_cast<lhs_rep>(assigned_common_rep);
559+
conversion::saturating_cast<lhs_rep>(assigned_common_rep);
676560
lhs.store(underlying::traits<lhs_value_type>::from_rep(assigned_rep));
677561
return out;
678562
}

src/primitive/impl.cppm

Lines changed: 5 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
module;
2-
#include <cmath>
32
#include <cstdint>
4-
#include <limits>
53
#include <tuple>
64
#include <type_traits>
75

86
export module mcpplibs.primitives.primitive.impl;
97

10-
import mcpplibs.primitives.underlying;
8+
import mcpplibs.primitives.conversion.underlying;
9+
import mcpplibs.primitives.underlying.traits;
1110
import mcpplibs.primitives.policy.traits;
1211
import mcpplibs.primitives.policy.handler;
1312
import mcpplibs.primitives.policy.impl;
@@ -56,73 +55,6 @@ private:
5655
cross_underlying_constructible_v<U> &&
5756
policy_allows_underlying_bridge_v<value_type, U>;
5857

59-
template <typename TargetRep, typename SourceRep>
60-
static constexpr auto saturating_rep_cast_(SourceRep value) noexcept
61-
-> std::remove_cvref_t<TargetRep> {
62-
using target_rep_type = std::remove_cvref_t<TargetRep>;
63-
using source_rep_type = std::remove_cvref_t<SourceRep>;
64-
65-
if constexpr (std_integer<target_rep_type> && std_integer<source_rep_type>) {
66-
if constexpr (std::is_signed_v<source_rep_type>) {
67-
auto const signed_value = static_cast<std::intmax_t>(value);
68-
if constexpr (std::is_signed_v<target_rep_type>) {
69-
if (signed_value < static_cast<std::intmax_t>(
70-
std::numeric_limits<target_rep_type>::min())) {
71-
return std::numeric_limits<target_rep_type>::lowest();
72-
}
73-
if (signed_value > static_cast<std::intmax_t>(
74-
std::numeric_limits<target_rep_type>::max())) {
75-
return std::numeric_limits<target_rep_type>::max();
76-
}
77-
return static_cast<target_rep_type>(value);
78-
} else {
79-
if (signed_value < 0) {
80-
return std::numeric_limits<target_rep_type>::lowest();
81-
}
82-
if (static_cast<std::uintmax_t>(signed_value) >
83-
static_cast<std::uintmax_t>(
84-
std::numeric_limits<target_rep_type>::max())) {
85-
return std::numeric_limits<target_rep_type>::max();
86-
}
87-
return static_cast<target_rep_type>(value);
88-
}
89-
} else {
90-
auto const unsigned_value = static_cast<std::uintmax_t>(value);
91-
if (unsigned_value >
92-
static_cast<std::uintmax_t>(
93-
std::numeric_limits<target_rep_type>::max())) {
94-
return std::numeric_limits<target_rep_type>::max();
95-
}
96-
return static_cast<target_rep_type>(value);
97-
}
98-
} else if constexpr (std_integer<target_rep_type> &&
99-
std_floating<source_rep_type>) {
100-
if (std::isnan(value)) {
101-
return target_rep_type{};
102-
}
103-
if (std::isinf(value)) {
104-
return value < static_cast<source_rep_type>(0)
105-
? std::numeric_limits<target_rep_type>::lowest()
106-
: std::numeric_limits<target_rep_type>::max();
107-
}
108-
109-
auto const normalized = static_cast<long double>(value);
110-
auto const min_value = static_cast<long double>(
111-
std::numeric_limits<target_rep_type>::lowest());
112-
auto const max_value = static_cast<long double>(
113-
std::numeric_limits<target_rep_type>::max());
114-
if (normalized < min_value) {
115-
return std::numeric_limits<target_rep_type>::lowest();
116-
}
117-
if (normalized > max_value) {
118-
return std::numeric_limits<target_rep_type>::max();
119-
}
120-
return static_cast<target_rep_type>(value);
121-
} else {
122-
return static_cast<target_rep_type>(value);
123-
}
124-
}
125-
12658
template <underlying_type Target, underlying_type Source>
12759
static constexpr auto convert_underlying_(Source source) noexcept -> Target {
12860
using source_value_type = std::remove_cv_t<Source>;
@@ -131,8 +63,9 @@ private:
13163
underlying::traits<std::remove_cv_t<Target>>::rep_type;
13264

13365
auto const source_rep = underlying::traits<source_value_type>::to_rep(source);
134-
auto const target_rep = saturating_rep_cast_<target_rep_type>(
135-
static_cast<source_rep_type>(source_rep));
66+
auto const target_rep =
67+
conversion::saturating_cast<target_rep_type>(
68+
static_cast<source_rep_type>(source_rep));
13669
return underlying::traits<std::remove_cv_t<Target>>::from_rep(target_rep);
13770
}
13871

0 commit comments

Comments
 (0)