diff --git a/src/algorithms/limits.cppm b/src/algorithms/limits.cppm index 9fb3242..9dc40dc 100644 --- a/src/algorithms/limits.cppm +++ b/src/algorithms/limits.cppm @@ -6,7 +6,7 @@ module; export module mcpplibs.primitives.algorithms.limits; -import mcpplibs.primitives.underlying.traits; +import mcpplibs.primitives.underlying; namespace mcpplibs::primitives::algorithms::details { diff --git a/src/literals/literals.cppm b/src/literals/literals.cppm index 1667abc..913fb9b 100644 --- a/src/literals/literals.cppm +++ b/src/literals/literals.cppm @@ -11,7 +11,7 @@ export module mcpplibs.primitives.literals; import mcpplibs.primitives.algorithms.limits; import mcpplibs.primitives.conversion.traits; -import mcpplibs.primitives.underlying.traits; +import mcpplibs.primitives.underlying; namespace mcpplibs::primitives::literals::details { diff --git a/src/underlying/impl.cppm b/src/underlying/impl.cppm deleted file mode 100644 index 6aaa4d1..0000000 --- a/src/underlying/impl.cppm +++ /dev/null @@ -1,5 +0,0 @@ -module; - -export module mcpplibs.primitives.underlying.impl; - -export import mcpplibs.primitives.underlying.traits; diff --git a/src/underlying/traits.cppm b/src/underlying/traits.cppm deleted file mode 100644 index 7bf4674..0000000 --- a/src/underlying/traits.cppm +++ /dev/null @@ -1,235 +0,0 @@ -module; -#include -#include - -export module mcpplibs.primitives.underlying.traits; - -export namespace mcpplibs::primitives { - -template -concept std_bool = std::same_as, bool>; - -template -concept std_char = std::same_as, char> || - std::same_as, signed char> || - std::same_as, unsigned char> || - std::same_as, wchar_t> || - std::same_as, char8_t> || - std::same_as, char16_t> || - std::same_as, char32_t>; - -template -concept std_floating = std::floating_point>; - -template -concept std_integer = - std::integral> && (!std_bool) && (!std_char); - -template -concept std_numeric = std_integer || std_floating; - -template -concept std_underlying_type = - std_bool || std_char || std_integer || std_floating; - -namespace underlying { - -enum class category { - boolean, - character, - integer, - floating, -}; - -template struct traits { - using value_type = void; - using rep_type = void; - - static constexpr bool enabled = false; - - static constexpr auto kind = static_cast(-1); - - template static constexpr rep_type to_rep(U) noexcept {} - - template static constexpr value_type from_rep(U) noexcept {} - - template static constexpr bool is_valid_rep(U) noexcept { - return false; - } -}; - -template -struct common_rep_traits { - using type = void; - static constexpr bool enabled = false; -}; - -template -struct common_rep_traits< - LhsRep, RhsRep, - std::void_t, - std::remove_cv_t>>> { - using type = - std::common_type_t, std::remove_cv_t>; - static constexpr bool enabled = true; -}; - -template -struct traits { - using value_type = std::remove_cv_t; - using rep_type = value_type; - - static constexpr bool enabled = true; - - static constexpr category kind = [] { - if constexpr (std_bool) { - return category::boolean; - } else if constexpr (std_char) { - return category::character; - } else if constexpr (std_integer) { - 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 underlying -} // namespace mcpplibs::primitives - -namespace mcpplibs::primitives::underlying::details { - -template -concept enabled = traits>::enabled; - -template -concept has_rep_type = - enabled && requires { typename traits>::rep_type; }; - -template -concept has_category = enabled && requires { - { traits>::kind } -> std::convertible_to; -}; - -template -concept has_rep_bridge = - has_rep_type && - requires(std::remove_cv_t value, - typename traits>::rep_type rep) { - { - traits>::to_rep(value) - } -> std::same_as>::rep_type>; - { - traits>::from_rep(rep) - } -> std::same_as>; - { traits>::is_valid_rep(rep) } -> std::same_as; - }; - -template -concept has_std_rep_type = - has_rep_type && - std_underlying_type>::rep_type>; - -template -concept has_custom_numeric_rep_type = - has_rep_type && - requires(typename traits>::rep_type a, - typename traits>::rep_type b) { - { a + b }; - { a - b }; - { a * b }; - { a / b }; - { a == b } -> std::convertible_to; - }; - -template -concept has_supported_rep_type = - has_std_rep_type || has_custom_numeric_rep_type; - -template -consteval category category_of_std_underlying_type() { - if constexpr (std_bool) { - return category::boolean; - } else if constexpr (std_char) { - return category::character; - } else if constexpr (std_integer) { - return category::integer; - } else { - return category::floating; - } -} - -template -concept has_consistent_category = - has_category && has_supported_rep_type && - ((has_std_rep_type && - (traits>::kind == - category_of_std_underlying_type< - typename traits>::rep_type>())) || - (!has_std_rep_type && - (traits>::kind == category::integer || - traits>::kind == category::floating))); - -template -concept has_common_rep = - common_rep_traits, - std::remove_cv_t>::enabled && - requires { - typename common_rep_traits, - std::remove_cv_t>::type; - }; - -} // namespace mcpplibs::primitives::underlying::details - -export namespace mcpplibs::primitives { - -template -concept underlying_type = - underlying::details::enabled && underlying::details::has_category && - underlying::details::has_rep_bridge && - underlying::details::has_supported_rep_type && - underlying::details::has_consistent_category; - -template -concept underlying_operand = underlying_type>; - -template -concept boolean_underlying_type = - underlying_type && (underlying::traits>::kind == - underlying::category::boolean); - -template -concept character_underlying_type = - underlying_type && (underlying::traits>::kind == - underlying::category::character); - -template -concept integer_underlying_type = - underlying_type && (underlying::traits>::kind == - underlying::category::integer); - -template -concept floating_underlying_type = - underlying_type && (underlying::traits>::kind == - underlying::category::floating); - -template -concept numeric_underlying_type = - integer_underlying_type || floating_underlying_type; - -template -concept has_common_rep = underlying::details::has_common_rep; - -template -using common_rep_t = - underlying::common_rep_traits, - std::remove_cv_t>::type; -} // namespace mcpplibs::primitives diff --git a/src/underlying/underlying.cppm b/src/underlying/underlying.cppm index 95ce243..b5d6cb8 100644 --- a/src/underlying/underlying.cppm +++ b/src/underlying/underlying.cppm @@ -1,6 +1,235 @@ module; +#include +#include export module mcpplibs.primitives.underlying; -export import mcpplibs.primitives.underlying.traits; -export import mcpplibs.primitives.underlying.impl; +export namespace mcpplibs::primitives { + +template +concept std_bool = std::same_as, bool>; + +template +concept std_char = std::same_as, char> || + std::same_as, signed char> || + std::same_as, unsigned char> || + std::same_as, wchar_t> || + std::same_as, char8_t> || + std::same_as, char16_t> || + std::same_as, char32_t>; + +template +concept std_floating = std::floating_point>; + +template +concept std_integer = + std::integral> && (!std_bool) && (!std_char); + +template +concept std_numeric = std_integer || std_floating; + +template +concept std_underlying_type = + std_bool || std_char || std_integer || std_floating; + +namespace underlying { + +enum class category { + boolean, + character, + integer, + floating, +}; + +template struct traits { + using value_type = void; + using rep_type = void; + + static constexpr bool enabled = false; + + static constexpr auto kind = static_cast(-1); + + template static constexpr rep_type to_rep(U) noexcept {} + + template static constexpr value_type from_rep(U) noexcept {} + + template static constexpr bool is_valid_rep(U) noexcept { + return false; + } +}; + +template +struct common_rep_traits { + using type = void; + static constexpr bool enabled = false; +}; + +template +struct common_rep_traits< + LhsRep, RhsRep, + std::void_t, + std::remove_cv_t>>> { + using type = + std::common_type_t, std::remove_cv_t>; + static constexpr bool enabled = true; +}; + +template +struct traits { + using value_type = std::remove_cv_t; + using rep_type = value_type; + + static constexpr bool enabled = true; + + static constexpr category kind = [] { + if constexpr (std_bool) { + return category::boolean; + } else if constexpr (std_char) { + return category::character; + } else if constexpr (std_integer) { + 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 underlying +} // namespace mcpplibs::primitives + +namespace mcpplibs::primitives::underlying::details { + +template +concept enabled = traits>::enabled; + +template +concept has_rep_type = + enabled && requires { typename traits>::rep_type; }; + +template +concept has_category = enabled && requires { + { traits>::kind } -> std::convertible_to; +}; + +template +concept has_rep_bridge = + has_rep_type && + requires(std::remove_cv_t value, + typename traits>::rep_type rep) { + { + traits>::to_rep(value) + } -> std::same_as>::rep_type>; + { + traits>::from_rep(rep) + } -> std::same_as>; + { traits>::is_valid_rep(rep) } -> std::same_as; + }; + +template +concept has_std_rep_type = + has_rep_type && + std_underlying_type>::rep_type>; + +template +concept has_custom_numeric_rep_type = + has_rep_type && + requires(typename traits>::rep_type a, + typename traits>::rep_type b) { + { a + b }; + { a - b }; + { a * b }; + { a / b }; + { a == b } -> std::convertible_to; + }; + +template +concept has_supported_rep_type = + has_std_rep_type || has_custom_numeric_rep_type; + +template +consteval category category_of_std_underlying_type() { + if constexpr (std_bool) { + return category::boolean; + } else if constexpr (std_char) { + return category::character; + } else if constexpr (std_integer) { + return category::integer; + } else { + return category::floating; + } +} + +template +concept has_consistent_category = + has_category && has_supported_rep_type && + ((has_std_rep_type && + (traits>::kind == + category_of_std_underlying_type< + typename traits>::rep_type>())) || + (!has_std_rep_type && + (traits>::kind == category::integer || + traits>::kind == category::floating))); + +template +concept has_common_rep = + common_rep_traits, + std::remove_cv_t>::enabled && + requires { + typename common_rep_traits, + std::remove_cv_t>::type; + }; + +} // namespace mcpplibs::primitives::underlying::details + +export namespace mcpplibs::primitives { + +template +concept underlying_type = + underlying::details::enabled && underlying::details::has_category && + underlying::details::has_rep_bridge && + underlying::details::has_supported_rep_type && + underlying::details::has_consistent_category; + +template +concept underlying_operand = underlying_type>; + +template +concept boolean_underlying_type = + underlying_type && (underlying::traits>::kind == + underlying::category::boolean); + +template +concept character_underlying_type = + underlying_type && (underlying::traits>::kind == + underlying::category::character); + +template +concept integer_underlying_type = + underlying_type && (underlying::traits>::kind == + underlying::category::integer); + +template +concept floating_underlying_type = + underlying_type && (underlying::traits>::kind == + underlying::category::floating); + +template +concept numeric_underlying_type = + integer_underlying_type || floating_underlying_type; + +template +concept has_common_rep = underlying::details::has_common_rep; + +template +using common_rep_t = + underlying::common_rep_traits, + std::remove_cv_t>::type; +} // namespace mcpplibs::primitives