-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimpl.cppm
More file actions
152 lines (114 loc) · 4.97 KB
/
impl.cppm
File metadata and controls
152 lines (114 loc) · 4.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
module;
#include <concepts>
#include <cstddef>
#include <cstdint>
#include <stdexcept>
#include <limits>
#include <type_traits>
export module mcpplibs.primitives.underlying.impl;
import mcpplibs.primitives.underlying.traits;
export
template <mcpplibs::primitives::std_underlying_type T>
struct mcpplibs::primitives::underlying::traits<T> {
using value_type = std::remove_cv_t<T>;
using rep_type = value_type;
static constexpr bool enabled = true;
static constexpr category kind = [] {
if constexpr (std_bool<value_type>) {
return category::boolean;
} else if constexpr (std_char<value_type>) {
return category::character;
} else if constexpr (std_integer<value_type>) {
return category::integer;
} else {
return category::floating;
}
}();
static constexpr rep_type to_rep(value_type value) noexcept { return value; }
static constexpr value_type from_rep(rep_type value) noexcept {
return value;
}
static constexpr bool is_valid_rep(rep_type) noexcept { return true; }
};
namespace mcpplibs::primitives::underlying::details {
template <std::integral T>
consteval auto cast_integer_literal(unsigned long long value) -> T {
if (value > static_cast<unsigned long long>(std::numeric_limits<T>::max())) {
throw std::out_of_range{"integer literal is out of range for target underlying type"};
}
return static_cast<T>(value);
}
template <std::floating_point T>
consteval auto cast_floating_literal(long double value) -> T {
if (!(value < 0 || value >= 0)) {
throw std::out_of_range{"floating literal must be finite"};
}
auto const lowest = static_cast<long double>(std::numeric_limits<T>::lowest());
if (auto const max = static_cast<long double>(std::numeric_limits<T>::max());
value < lowest || value > max) {
throw std::out_of_range{"floating literal is out of range for target underlying type"};
}
return static_cast<T>(value);
}
} // namespace mcpplibs::primitives::underlying::details
export namespace mcpplibs::primitives::literals {
consteval auto operator""_uchar(const char value) -> unsigned char {
return static_cast<unsigned char>(value);
}
consteval auto operator""_char8(const char8_t value) -> char8_t { return value; }
consteval auto operator""_char16(const char16_t value) -> char16_t { return value; }
consteval auto operator""_char32(const char32_t value) -> char32_t { return value; }
consteval auto operator""_wchar(const wchar_t value) -> wchar_t { return value; }
consteval auto operator""_u8(const unsigned long long value) -> std::uint8_t {
return underlying::details::cast_integer_literal<std::uint8_t>(value);
}
consteval auto operator""_u16(const unsigned long long value) -> std::uint16_t {
return underlying::details::cast_integer_literal<std::uint16_t>(value);
}
consteval auto operator""_u32(const unsigned long long value) -> std::uint32_t {
return underlying::details::cast_integer_literal<std::uint32_t>(value);
}
consteval auto operator""_u64(const unsigned long long value) -> std::uint64_t {
return underlying::details::cast_integer_literal<std::uint64_t>(value);
}
consteval auto operator""_size(const unsigned long long value) -> std::size_t {
return underlying::details::cast_integer_literal<std::size_t>(value);
}
consteval auto operator""_diff(const unsigned long long value)
-> std::ptrdiff_t {
return underlying::details::cast_integer_literal<std::ptrdiff_t>(value);
}
consteval auto operator""_i8(const unsigned long long value) -> std::int8_t {
return underlying::details::cast_integer_literal<std::int8_t>(value);
}
consteval auto operator""_i16(const unsigned long long value) -> std::int16_t {
return underlying::details::cast_integer_literal<std::int16_t>(value);
}
consteval auto operator""_i32(const unsigned long long value) -> std::int32_t {
return underlying::details::cast_integer_literal<std::int32_t>(value);
}
consteval auto operator""_i64(const unsigned long long value) -> std::int64_t {
return underlying::details::cast_integer_literal<std::int64_t>(value);
}
consteval auto operator""_f32(const unsigned long long value) -> float {
return underlying::details::cast_floating_literal<float>(
static_cast<long double>(value));
}
consteval auto operator""_f32(const long double value) -> float {
return underlying::details::cast_floating_literal<float>(value);
}
consteval auto operator""_f64(const unsigned long long value) -> double {
return underlying::details::cast_floating_literal<double>(
static_cast<long double>(value));
}
consteval auto operator""_f64(const long double value) -> double {
return underlying::details::cast_floating_literal<double>(value);
}
consteval auto operator""_f80(const unsigned long long value) -> long double {
return underlying::details::cast_floating_literal<long double>(
static_cast<long double>(value));
}
consteval auto operator""_f80(const long double value) -> long double {
return underlying::details::cast_floating_literal<long double>(value);
}
} // namespace mcpplibs::primitives::literals