Skip to content

Commit bd7c8d6

Browse files
feat: Add underlying concepts and traits in submodule traits
1 parent 54f446e commit bd7c8d6

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed

src/primitive.cppm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module;
2+
3+
export module mcpplibs.primitive;
4+
5+
export import mcpplibs.primitive.traits;

src/traits/traits.cppm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module;
2+
3+
export module mcpplibs.primitive.traits;
4+
5+
export import mcpplibs.primitive.traits.underlying;

src/traits/underlying.cppm

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
module;
2+
#include <concepts>
3+
#include <type_traits>
4+
5+
export module mcpplibs.primitive.traits.underlying;
6+
7+
export namespace mcpplibs::primitive {
8+
9+
template <typename T>
10+
concept std_bool = std::same_as<std::remove_cv_t<T>, bool>;
11+
12+
template <typename T>
13+
concept std_char = std::same_as<std::remove_cv_t<T>, char> ||
14+
std::same_as<std::remove_cv_t<T>, signed char> ||
15+
std::same_as<std::remove_cv_t<T>, unsigned char> ||
16+
std::same_as<std::remove_cv_t<T>, wchar_t> ||
17+
std::same_as<std::remove_cv_t<T>, char8_t> ||
18+
std::same_as<std::remove_cv_t<T>, char16_t> ||
19+
std::same_as<std::remove_cv_t<T>, char32_t>;
20+
21+
template <typename T>
22+
concept std_floating = std::floating_point<std::remove_cv_t<T>>;
23+
24+
template <typename T>
25+
concept std_integer =
26+
std::integral<std::remove_cv_t<T>> && (!std_bool<T>) && (!std_char<T>);
27+
28+
template <typename T>
29+
concept std_underlying_type =
30+
std_bool<T> || std_char<T> || std_integer<T> || std_floating<T>;
31+
32+
namespace underlying {
33+
34+
enum class category {
35+
boolean,
36+
character,
37+
integer,
38+
floating,
39+
};
40+
41+
template <typename T> struct traits {
42+
static constexpr bool enabled = false;
43+
};
44+
45+
template <std_underlying_type T> struct traits<T> {
46+
using value_type = std::remove_cv_t<T>;
47+
using rep_type = value_type;
48+
49+
static constexpr bool enabled = true;
50+
51+
static constexpr category kind = [] {
52+
if constexpr (std_bool<value_type>) {
53+
return category::boolean;
54+
} else if constexpr (std_char<value_type>) {
55+
return category::character;
56+
} else if constexpr (std_integer<value_type>) {
57+
return category::integer;
58+
} else {
59+
return category::floating;
60+
}
61+
}();
62+
63+
static constexpr rep_type to_rep(value_type value) noexcept { return value; }
64+
65+
static constexpr value_type from_rep(rep_type value) noexcept {
66+
return value;
67+
}
68+
69+
static constexpr bool is_valid_rep(rep_type) noexcept { return true; }
70+
};
71+
} // namespace underlying
72+
73+
} // namespace mcpplibs::primitive
74+
75+
namespace mcpplibs::primitive::underlying::details {
76+
77+
template <typename T>
78+
concept enabled = traits<std::remove_cv_t<T>>::enabled;
79+
80+
template <typename T>
81+
concept has_rep_type =
82+
enabled<T> && requires { typename traits<std::remove_cv_t<T>>::rep_type; };
83+
84+
template <typename T>
85+
concept has_category = enabled<T> && requires {
86+
{ traits<std::remove_cv_t<T>>::kind } -> std::convertible_to<category>;
87+
};
88+
89+
template <typename T>
90+
concept has_rep_bridge =
91+
has_rep_type<T> &&
92+
requires(std::remove_cv_t<T> value,
93+
typename traits<std::remove_cv_t<T>>::rep_type rep) {
94+
{
95+
traits<std::remove_cv_t<T>>::to_rep(value)
96+
} -> std::same_as<typename traits<std::remove_cv_t<T>>::rep_type>;
97+
{
98+
traits<std::remove_cv_t<T>>::from_rep(rep)
99+
} -> std::same_as<std::remove_cv_t<T>>;
100+
{ traits<std::remove_cv_t<T>>::is_valid_rep(rep) } -> std::same_as<bool>;
101+
};
102+
103+
template <typename T>
104+
concept has_std_rep_type =
105+
has_rep_type<T> &&
106+
std_underlying_type<typename traits<std::remove_cv_t<T>>::rep_type>;
107+
108+
template <std_underlying_type T>
109+
consteval category category_of_std_underlying_type() {
110+
if constexpr (std_bool<T>) {
111+
return category::boolean;
112+
} else if constexpr (std_char<T>) {
113+
return category::character;
114+
} else if constexpr (std_integer<T>) {
115+
return category::integer;
116+
} else {
117+
return category::floating;
118+
}
119+
}
120+
121+
template <typename T>
122+
concept has_consistent_category =
123+
has_category<T> && has_std_rep_type<T> &&
124+
(traits<std::remove_cv_t<T>>::kind ==
125+
category_of_std_underlying_type<
126+
typename traits<std::remove_cv_t<T>>::rep_type>());
127+
128+
} // namespace mcpplibs::primitive::underlying::details
129+
130+
export namespace mcpplibs::primitive {
131+
132+
template <typename T>
133+
concept underlying_type =
134+
underlying::details::enabled<T> && underlying::details::has_category<T> &&
135+
underlying::details::has_rep_bridge<T> &&
136+
underlying::details::has_std_rep_type<T> &&
137+
underlying::details::has_consistent_category<T>;
138+
139+
} // namespace mcpplibs::primitive

0 commit comments

Comments
 (0)