From 7a730fde582d5ebe4092d11b58a3d823d8524e50 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Mon, 5 Jun 2023 19:36:22 +0200 Subject: [PATCH] refactor: `constant_unit` abstraction removed and replaced with regular `named_unit` --- .../include/mp-units/bits/unit_concepts.h | 23 +------ src/core/include/mp-units/unit.h | 61 +++---------------- .../hep/include/mp-units/systems/hep/hep.h | 7 ++- .../systems/international/international.h | 2 +- .../include/mp-units/systems/si/constants.h | 50 ++++++--------- test/unit_test/static/concepts_test.cpp | 12 ++-- test/unit_test/static/unit_symbol_test.cpp | 6 +- test/unit_test/static/unit_test.cpp | 49 ++++++++------- 8 files changed, 66 insertions(+), 144 deletions(-) diff --git a/src/core/include/mp-units/bits/unit_concepts.h b/src/core/include/mp-units/bits/unit_concepts.h index 50fddbad..152ca819 100644 --- a/src/core/include/mp-units/bits/unit_concepts.h +++ b/src/core/include/mp-units/bits/unit_concepts.h @@ -50,10 +50,6 @@ struct scaled_unit; template struct named_unit; -template - requires(!Symbol.empty()) -struct constant_unit; - namespace detail { template @@ -69,21 +65,13 @@ inline constexpr bool is_specialization_of_named_unit = false; template inline constexpr bool is_specialization_of_named_unit> = true; -template -void to_base_specialization_of_constant_unit(const volatile constant_unit*); - -template -inline constexpr bool is_derived_from_specialization_of_constant_unit = - requires(T* t) { to_base_specialization_of_constant_unit(t); }; - /** * @brief A concept matching all units with special names * * Satisfied by all unit types derived from the specialization of `named_unit` (but not constant units). */ template -concept NamedUnit = Unit && detail::is_derived_from_specialization_of_named_unit && - (!detail::is_derived_from_specialization_of_constant_unit); +concept NamedUnit = Unit && detail::is_derived_from_specialization_of_named_unit; } // namespace detail @@ -144,12 +132,6 @@ inline constexpr bool is_specialization_of_unit = false; template inline constexpr bool is_specialization_of_unit> = true; -template -inline constexpr bool is_specialization_of_constant_unit = false; - -template -inline constexpr bool is_specialization_of_constant_unit> = true; - template inline constexpr bool is_specialization_of_prefixed_unit = false; @@ -158,8 +140,7 @@ inline constexpr bool is_specialization_of_prefixed_unit requires requires(T* t) { is_unit_impl(t); } -inline constexpr bool is_unit = !is_specialization_of_named_unit && !is_specialization_of_constant_unit && - !is_specialization_of_prefixed_unit; +inline constexpr bool is_unit = !is_specialization_of_named_unit && !is_specialization_of_prefixed_unit; template [[nodiscard]] consteval bool has_associated_quantity(U); diff --git a/src/core/include/mp-units/unit.h b/src/core/include/mp-units/unit.h index 0052f12b..9996f7e4 100644 --- a/src/core/include/mp-units/unit.h +++ b/src/core/include/mp-units/unit.h @@ -162,41 +162,6 @@ struct named_unit : std::remove_const_t { static constexpr auto quantity_spec = QS; }; -/** - * @brief A unit of a physical constant - * - * Defines a unit of a physical constant together with its value encoded as a unit ratio. - * - * This allows moving all of the constant-related ratio manipulation to the compile-time domain - * (i.e. multiplying and then dividing by the same constant will eliminate the item from the final - * type). - * As a result we have faster runtime performance and no precision loss due to eager floating-point - * operations. Also, if the user prefers integral types for a quantity representation, this will - * not force the user to convert to a floating-point type right away. Only when a final quantity - * number needs to actually account for the constant value, the floating-point operation (if any) - * can be triggered lazily with the `value_cast()`. - * - * For example: - * - * @code{.cpp} - * inline constexpr struct standard_gravity_unit : - * constant_unit<"g", mag * metre / square(second)> {} standard_gravity_unit; - * @endcode - * - * @note A common convention in this library is to assign the same name for a type and an object of this type. - * Besides defining them user never works with the unit types in the source code. All operations - * are done on the objects. Contrarily, the unit types are the only one visible in the compilation - * errors. Having them of the same names improves user experience and somehow blurs those separate domains. - * - * @tparam Symbol a short text representation of the constant - * - * @note Constant symbol is printed in the text output encapsulated inside square brackets `[]` - * and before any regular units - */ -template - requires(!Symbol.empty()) -struct constant_unit : named_unit<'[' + Symbol + ']', U> {}; - /** * @brief A prefixed unit * @@ -400,23 +365,15 @@ template template [[nodiscard]] consteval bool less(Lhs, Rhs) { - if constexpr ((is_derived_from_specialization_of_constant_unit && - is_derived_from_specialization_of_constant_unit) || - (!is_derived_from_specialization_of_constant_unit && - !is_derived_from_specialization_of_constant_unit)) { - if constexpr (requires { - Lhs::symbol; - Rhs::symbol; - }) - // prefer symbols comparison if possible as it gives typically better results - // i.e. it puts upper case in from so `N m` is correct - return Lhs::symbol < Rhs::symbol; - else - return type_name() < type_name(); - } else { - // put constants at the front of units list in the expression - return is_derived_from_specialization_of_constant_unit; - } + if constexpr (requires { + Lhs::symbol; + Rhs::symbol; + }) + // prefer symbols comparison if possible as it gives typically better results + // i.e. it puts upper case in from so `N m` is correct + return Lhs::symbol < Rhs::symbol; + else + return type_name() < type_name(); } diff --git a/src/systems/hep/include/mp-units/systems/hep/hep.h b/src/systems/hep/include/mp-units/systems/hep/hep.h index e9e1dfc0..8e6e2062 100644 --- a/src/systems/hep/include/mp-units/systems/hep/hep.h +++ b/src/systems/hep/include/mp-units/systems/hep/hep.h @@ -42,6 +42,9 @@ inline constexpr struct barn : named_unit<"b", mag_power<10, -28> * square(si::m inline constexpr struct electron_mass : named_unit<"m_e", mag * mag_power<10, -31> * si::kilogram> {} electron_mass; inline constexpr struct proton_mass : named_unit<"m_p", mag * mag_power<10, -27> * si::kilogram> {} proton_mass; inline constexpr struct neutron_mass : named_unit<"m_n", mag * mag_power<10, -27> * si::kilogram> {} neutron_mass; + +// speed +inline constexpr struct speed_of_light : decltype(si::si2019::speed_of_light_in_vacuum) {} speed_of_light; // clang-format on namespace unit_symbols { @@ -89,8 +92,8 @@ inline constexpr auto m_e = electron_mass; inline constexpr auto m_p = proton_mass; inline constexpr auto m_n = neutron_mass; -inline constexpr auto c = si::si2019::speed_of_light_in_vacuum_unit; -inline constexpr auto c2 = square(si::si2019::speed_of_light_in_vacuum_unit); +inline constexpr auto c = speed_of_light; +inline constexpr auto c2 = square(speed_of_light); } // namespace unit_symbols diff --git a/src/systems/international/include/mp-units/systems/international/international.h b/src/systems/international/include/mp-units/systems/international/international.h index 2660b6d6..dc0731f6 100644 --- a/src/systems/international/include/mp-units/systems/international/international.h +++ b/src/systems/international/include/mp-units/systems/international/international.h @@ -56,7 +56,7 @@ inline constexpr struct knot : named_unit<"kn", nautical_mile / si::hour> {} kno inline constexpr struct poundal : named_unit<"pdl", pound * foot / square(si::second)> {} poundal; // https://en.wikipedia.org/wiki/Pound_(force) -inline constexpr struct pound_force : named_unit<"lbf", pound * si::standard_gravity_unit> {} pound_force; +inline constexpr struct pound_force : named_unit<"lbf", pound * si::standard_gravity> {} pound_force; // https://en.wikipedia.org/wiki/Kip_(unit), inline constexpr struct kip : decltype(si::kilo) {} kip; diff --git a/src/systems/si/include/mp-units/systems/si/constants.h b/src/systems/si/include/mp-units/systems/si/constants.h index 26ee967e..a0ad268d 100644 --- a/src/systems/si/include/mp-units/systems/si/constants.h +++ b/src/systems/si/include/mp-units/systems/si/constants.h @@ -23,7 +23,6 @@ #pragma once #include -#include #include namespace mp_units::si { @@ -31,42 +30,29 @@ namespace mp_units::si { namespace si2019 { // clang-format off -inline constexpr struct hyperfine_structure_transition_frequency_of_cs_unit : - constant_unit * hertz> {} hyperfine_structure_transition_frequency_of_cs_unit; -inline constexpr struct speed_of_light_in_vacuum_unit : - constant_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum_unit; -inline constexpr struct planck_constant_unit : - constant_unit<"h", mag * mag_power<10, -34> * joule * second> {} planck_constant_unit; -inline constexpr struct elementary_charge_unit : - constant_unit<"e", mag * mag_power<10, -19> * coulomb> {} elementary_charge_unit; -inline constexpr struct boltzmann_constant_unit : - constant_unit<"k", mag * mag_power<10, -23> * joule / kelvin> {} boltzmann_constant_unit; -inline constexpr struct avogadro_constant_unit : - constant_unit<"NA", mag * mag_power<10, 23> * (1 / mole)> {} avogadro_constant_unit; -inline constexpr struct luminous_efficacy_unit : - constant_unit<"Kcd", mag<683> * lumen / watt> {} luminous_efficacy_unit; +inline constexpr struct hyperfine_structure_transition_frequency_of_cs : + named_unit * hertz> {} hyperfine_structure_transition_frequency_of_cs; +inline constexpr struct speed_of_light_in_vacuum : + named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum; +inline constexpr struct planck_constant : + named_unit<"h", mag * mag_power<10, -34> * joule * second> {} planck_constant; +inline constexpr struct elementary_charge : + named_unit<"e", mag * mag_power<10, -19> * coulomb> {} elementary_charge; +inline constexpr struct boltzmann_constant : + named_unit<"k", mag * mag_power<10, -23> * joule / kelvin> {} boltzmann_constant; +inline constexpr struct avogadro_constant : + named_unit<"N_A", mag * mag_power<10, 23> * (1 / mole)> {} avogadro_constant; +inline constexpr struct luminous_efficacy : + named_unit<"K_cd", mag<683> * lumen / watt> {} luminous_efficacy; // clang-format on -inline constexpr auto hyperfine_structure_transition_frequency_of_cs = - isq::frequency[hyperfine_structure_transition_frequency_of_cs_unit]; -inline constexpr auto speed_of_light_in_vacuum = isq::speed_of_light[speed_of_light_in_vacuum_unit]; -inline constexpr auto planck_constant = isq::action[planck_constant_unit]; -inline constexpr auto elementary_charge = isq::electric_charge[elementary_charge_unit]; -inline constexpr auto boltzmann_constant = isq::entropy[boltzmann_constant_unit]; -inline constexpr auto avogadro_constant = (1 / isq::amount_of_substance)[avogadro_constant_unit]; -// TODO uncomment the below when all the ISQ is provided -// inline constexpr auto luminous_efficacy = isq::luminous_efficacy_of_radiation[luminous_efficacy_unit]; - } // namespace si2019 // clang-format off -inline constexpr struct standard_gravity_unit : - constant_unit * metre / square(second)> {} standard_gravity_unit; -inline constexpr struct magnetic_constant_unit : - constant_unit * mag_pi * mag_power<10, -7> * henry / metre> {} magnetic_constant_unit; +inline constexpr struct standard_gravity : + named_unit * metre / square(second)> {} standard_gravity; +inline constexpr struct magnetic_constant : + named_unit * mag_pi * mag_power<10, -7> * henry / metre> {} magnetic_constant; // clang-format on -inline constexpr auto standard_gravity = isq::acceleration_of_free_fall[standard_gravity_unit]; -inline constexpr auto magnetic_constant = isq::magnetic_constant[magnetic_constant_unit]; - } // namespace mp_units::si diff --git a/test/unit_test/static/concepts_test.cpp b/test/unit_test/static/concepts_test.cpp index 085cb3b3..87b394dd 100644 --- a/test/unit_test/static/concepts_test.cpp +++ b/test/unit_test/static/concepts_test.cpp @@ -148,7 +148,7 @@ static_assert(Unit>); static_assert(Unit * si::second)>>); static_assert(Unit>); static_assert(Unit(si::metre))>>); -static_assert(Unit); +static_assert(Unit); static_assert(Unit, struct si::second>>); static_assert(Unit); static_assert(Unit>>); @@ -157,7 +157,6 @@ static_assert(!Unit>); static_assert(!Unit>); static_assert(!Unit>); static_assert(!Unit>); -static_assert(!Unit>); static_assert(!Unit, si::second>>); static_assert(!Unit); static_assert(!Unit); @@ -173,7 +172,7 @@ static_assert(!detail::NamedUnit>) static_assert(!detail::NamedUnit * si::second)>>); static_assert(!detail::NamedUnit>); static_assert(!detail::NamedUnit(si::metre))>>); -static_assert(!detail::NamedUnit); +static_assert(detail::NamedUnit); static_assert(!detail::NamedUnit, struct si::second>>); static_assert(!detail::NamedUnit); static_assert(!detail::NamedUnit>>); @@ -182,7 +181,6 @@ static_assert(!detail::NamedUnit>); static_assert(!detail::NamedUnit>); static_assert(!detail::NamedUnit>); static_assert(!detail::NamedUnit>); -static_assert(!detail::NamedUnit>); static_assert(!detail::NamedUnit, si::second>>); static_assert(!detail::NamedUnit); static_assert(!detail::NamedUnit); @@ -198,7 +196,7 @@ static_assert(!PrefixableUnit>); static_assert(!PrefixableUnit * si::second)>>); static_assert(!PrefixableUnit>); static_assert(!PrefixableUnit(si::metre))>>); -static_assert(!PrefixableUnit); +static_assert(PrefixableUnit); static_assert(!PrefixableUnit, struct si::second>>); static_assert(!PrefixableUnit); static_assert(!PrefixableUnit>>); @@ -207,7 +205,6 @@ static_assert(!PrefixableUnit>); static_assert(!PrefixableUnit>); static_assert(!PrefixableUnit>); static_assert(!PrefixableUnit>); -static_assert(!PrefixableUnit>); static_assert(!PrefixableUnit, si::second>>); static_assert(!PrefixableUnit); static_assert(!PrefixableUnit); @@ -223,7 +220,7 @@ static_assert(AssociatedUnit>); static_assert(AssociatedUnit * si::second)>>); static_assert(AssociatedUnit>); static_assert(AssociatedUnit(si::metre))>>); -static_assert(AssociatedUnit); +static_assert(AssociatedUnit); static_assert(AssociatedUnit, struct si::second>>); static_assert(AssociatedUnit); static_assert(AssociatedUnit>>); @@ -232,7 +229,6 @@ static_assert(!AssociatedUnit>); static_assert(!AssociatedUnit>); static_assert(!AssociatedUnit>); static_assert(!AssociatedUnit>); -static_assert(!AssociatedUnit>); static_assert(!AssociatedUnit, si::second>>); static_assert(!AssociatedUnit); static_assert(!AssociatedUnit); diff --git a/test/unit_test/static/unit_symbol_test.cpp b/test/unit_test/static/unit_symbol_test.cpp index 9ded737f..7c19d60b 100644 --- a/test/unit_test/static/unit_symbol_test.cpp +++ b/test/unit_test/static/unit_symbol_test.cpp @@ -159,9 +159,9 @@ static_assert(unit_symbol(pow<3, 5>(metre)) == "m^(3/5)"); static_assert(unit_symbol(pow<1, 2>(metre / second)) == "m^(1/2)/s^(1/2)"); // Physical constants -static_assert(unit_symbol(si2019::speed_of_light_in_vacuum_unit) == "[c]"); -static_assert(unit_symbol(gram * standard_gravity_unit * si2019::speed_of_light_in_vacuum_unit) == "[c] [g₀] g"); -static_assert(unit_symbol(gram / standard_gravity_unit) == "g/[g₀]"); +static_assert(unit_symbol(si2019::speed_of_light_in_vacuum) == "c"); +static_assert(unit_symbol(gram * standard_gravity * si2019::speed_of_light_in_vacuum) == "c g g₀"); +static_assert(unit_symbol(gram / standard_gravity) == "g/g₀"); #endif // __cpp_lib_constexpr_string diff --git a/test/unit_test/static/unit_test.cpp b/test/unit_test/static/unit_test.cpp index 598504e7..c905ded9 100644 --- a/test/unit_test/static/unit_test.cpp +++ b/test/unit_test/static/unit_test.cpp @@ -87,8 +87,8 @@ inline constexpr struct kilometre_ : decltype(si::kilo) {} kilometre; inline constexpr struct kilojoule_ : decltype(si::kilo) {} kilojoule; // physical constant units -inline constexpr struct standard_gravity_unit_ : constant_unit<"g", mag * metre / square(second)> {} standard_gravity_unit; -inline constexpr struct speed_of_light_in_vacuum_unit_ : constant_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum_unit; +inline constexpr struct standard_gravity_ : named_unit * metre / square(second)> {} standard_gravity; +inline constexpr struct speed_of_light_in_vacuum_ : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum; // clang-format on @@ -190,15 +190,15 @@ static_assert(joule != newton); static_assert(is_of_type); // constant_unit -static_assert(is_of_type); +static_assert(is_of_type); static_assert( - is_of_type>>>); -static_assert(get_canonical_unit(standard_gravity_unit).mag == mag); -static_assert(convertible(standard_gravity_unit, standard_gravity_unit)); -static_assert(convertible(standard_gravity_unit, metre / square(second))); -static_assert(standard_gravity_unit == standard_gravity_unit); -static_assert(standard_gravity_unit != metre / square(second)); // magnitude is different -static_assert(standard_gravity_unit.symbol == "[g]"); + is_of_type>>>); +static_assert(get_canonical_unit(standard_gravity).mag == mag); +static_assert(convertible(standard_gravity, standard_gravity)); +static_assert(convertible(standard_gravity, metre / square(second))); +static_assert(standard_gravity == standard_gravity); +static_assert(standard_gravity != metre / square(second)); // magnitude is different +static_assert(standard_gravity.symbol == basic_symbol_text{"g₀", "g_0"}); // prefixed_unit static_assert(is_of_type); @@ -333,15 +333,15 @@ static_assert(is_of_type, per>>); static_assert(is_of_type, per>>); -static_assert(is_of_type>); -static_assert(is_of_type>); -static_assert(is_of_type>>); -static_assert(is_of_type>>); -static_assert(is_of_type); -static_assert(is_of_type>); -static_assert(is_of_type>); +static_assert(is_of_type>); +static_assert(is_of_type>); +static_assert(is_of_type>>); +static_assert(is_of_type>>); +static_assert(is_of_type); +static_assert(is_of_type>); +static_assert(is_of_type>); static_assert(std::is_same_v); static_assert(std::is_same_v); @@ -374,11 +374,11 @@ static_assert( is_of_type, per>>); static_assert( - is_of_type>>>); -static_assert(get_canonical_unit(standard_gravity_unit).mag == mag); -static_assert(is_of_type>>>); +static_assert(get_canonical_unit(standard_gravity).mag == mag); +static_assert(is_of_type>>>); -static_assert(is_of_type>>); // operations commutativity @@ -532,7 +532,6 @@ static_assert(is_of_type, derived_unit>>>); static_assert(is_of_type, metre_>>); static_assert(is_of_type, metre_>>); -static_assert( - is_of_type>>); +static_assert(is_of_type>>); } // namespace