From 41be9b3e530e9a8001491064ef56969b04055dd4 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Tue, 4 Jun 2024 20:03:41 +0200 Subject: [PATCH 01/44] refactor: input value for a kalman filter example had a typo in the book --- example/kalman_filter/kalman_filter-example_6.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/kalman_filter/kalman_filter-example_6.cpp b/example/kalman_filter/kalman_filter-example_6.cpp index 59ce7a0fc..96cc1d38c 100644 --- a/example/kalman_filter/kalman_filter-example_6.cpp +++ b/example/kalman_filter/kalman_filter-example_6.cpp @@ -63,7 +63,7 @@ int main() const quantity process_noise_variance = 0.0001 * pow<2>(deg_C); const estimate initial{state{qp{60. * deg_C}}, 100. * deg_C}; - const std::array measurements = {qp{49.986 * deg_C}, qp{49.963 * deg_C}, qp{50.09 * deg_C}, qp{50.001 * deg_C}, + const std::array measurements = {qp{49.986 * deg_C}, qp{49.963 * deg_C}, qp{50.097 * deg_C}, qp{50.001 * deg_C}, qp{50.018 * deg_C}, qp{50.05 * deg_C}, qp{49.938 * deg_C}, qp{49.858 * deg_C}, qp{49.965 * deg_C}, qp{50.114 * deg_C}}; const quantity measurement_error = 0.1 * deg_C; From fb7758559308cd3d2b1e09ef1ab2a035a558418c Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Wed, 5 Jun 2024 08:13:15 +0200 Subject: [PATCH 02/44] refactor: system's units do not inherit from one another anymore Resolves #512 --- docs/users_guide/framework_basics/text_output.md | 2 +- src/systems/include/mp-units/systems/cgs.h | 10 +++------- src/systems/include/mp-units/systems/hep.h | 2 +- src/systems/include/mp-units/systems/iau.h | 2 +- src/systems/include/mp-units/systems/imperial.h | 6 +++--- src/systems/include/mp-units/systems/international.h | 6 +----- src/systems/include/mp-units/systems/natural.h | 6 +----- src/systems/include/mp-units/systems/si/units.h | 12 ++---------- src/systems/include/mp-units/systems/usc.h | 2 +- test/static/concepts_test.cpp | 10 +++++----- 10 files changed, 19 insertions(+), 39 deletions(-) diff --git a/docs/users_guide/framework_basics/text_output.md b/docs/users_guide/framework_basics/text_output.md index de8c96eaa..67bd4395d 100644 --- a/docs/users_guide/framework_basics/text_output.md +++ b/docs/users_guide/framework_basics/text_output.md @@ -48,7 +48,7 @@ and units of derived quantities. inline constexpr struct second : named_unit<"s", kind_of> {} second; inline constexpr struct metre : named_unit<"m", kind_of> {} metre; inline constexpr struct gram : named_unit<"g", kind_of> {} gram; - inline constexpr struct kilogram : decltype(kilo) {} kilogram; + inline constexpr auto kilogram = kilo; inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton; inline constexpr struct joule : named_unit<"J", newton * metre> {} joule; diff --git a/src/systems/include/mp-units/systems/cgs.h b/src/systems/include/mp-units/systems/cgs.h index f3e58e546..4a3645f56 100644 --- a/src/systems/include/mp-units/systems/cgs.h +++ b/src/systems/include/mp-units/systems/cgs.h @@ -35,13 +35,9 @@ MP_UNITS_EXPORT namespace mp_units::cgs { // clang-format off -#if MP_UNITS_COMP_MSVC -inline constexpr struct centimetre : si::centi_ {} centimetre; -#else -inline constexpr struct centimetre : decltype(si::centi) {} centimetre; -#endif -inline constexpr struct gram : decltype(si::gram) {} gram; -inline constexpr struct second : decltype(si::second) {} second; +inline constexpr auto centimetre = si::centi; +inline constexpr auto gram = si::gram; +inline constexpr auto second = si::second; inline constexpr struct gal : named_unit<"Gal", centimetre / square(second)> {} gal; inline constexpr struct dyne : named_unit<"dyn", gram * centimetre / square(second)> {} dyne; inline constexpr struct erg : named_unit<"erg", dyne * centimetre> {} erg; diff --git a/src/systems/include/mp-units/systems/hep.h b/src/systems/include/mp-units/systems/hep.h index 0267042f3..6020d07f9 100644 --- a/src/systems/include/mp-units/systems/hep.h +++ b/src/systems/include/mp-units/systems/hep.h @@ -57,7 +57,7 @@ inline constexpr struct proton_mass : named_unit<"m_p", mag_ratio<1'672'621'923' inline constexpr struct neutron_mass : named_unit<"m_n", mag_ratio<1'674'927'498'049, 1'000'000'000'000> * 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; +inline constexpr auto speed_of_light = si::si2019::speed_of_light_in_vacuum; // clang-format on namespace unit_symbols { diff --git a/src/systems/include/mp-units/systems/iau.h b/src/systems/include/mp-units/systems/iau.h index 8d4aeaa83..804f2ed05 100644 --- a/src/systems/include/mp-units/systems/iau.h +++ b/src/systems/include/mp-units/systems/iau.h @@ -50,7 +50,7 @@ inline constexpr struct Jupiter_mass : named_unit<"M_JUP", mag_ratio<1'898, 1'00 inline constexpr struct Earth_mass : named_unit<"M_EARTH", mag_ratio<59'742, 10'000> * mag_power<10, 24> * si::kilogram> {} Earth_mass; // length -inline constexpr struct astronomical_unit : decltype(si::astronomical_unit) {} astronomical_unit; +inline constexpr auto astronomical_unit = si::astronomical_unit; // https://en.wikipedia.org/wiki/Lunar_distance_(astronomy) inline constexpr struct lunar_distance : named_unit<"LD", mag<384'399> * si::kilo> {} lunar_distance; diff --git a/src/systems/include/mp-units/systems/imperial.h b/src/systems/include/mp-units/systems/imperial.h index 4398a8f5d..ffdd40029 100644 --- a/src/systems/include/mp-units/systems/imperial.h +++ b/src/systems/include/mp-units/systems/imperial.h @@ -54,9 +54,9 @@ inline constexpr struct link : named_unit<"li", mag_ratio<1, 100> * chain> {} li inline constexpr struct rod : named_unit<"rd", mag<25> * link> {} rod; // https://en.wikipedia.org/wiki/Imperial_units#Area -inline constexpr struct perch : decltype(square(rod)) {} perch; -inline constexpr struct rood : decltype(mag<40> * perch) {} rood; -inline constexpr struct acre : decltype(mag<4> * rood) {} acre; +inline constexpr struct perch : named_unit<"perch", square(rod)> {} perch; +inline constexpr struct rood : named_unit<"rood", mag<40> * perch> {} rood; +inline constexpr struct acre : named_unit<"acre", mag<4> * rood> {} acre; // https://en.wikipedia.org/wiki/Imperial_units#Volume inline constexpr struct gallon : named_unit<"gal", mag_ratio<454'609, 100'000> * si::litre> {} gallon; diff --git a/src/systems/include/mp-units/systems/international.h b/src/systems/include/mp-units/systems/international.h index 0b680ce3c..d4de6a310 100644 --- a/src/systems/include/mp-units/systems/international.h +++ b/src/systems/include/mp-units/systems/international.h @@ -67,11 +67,7 @@ inline constexpr struct poundal : named_unit<"pdl", pound * foot / square(si::se inline constexpr struct pound_force : named_unit<"lbf", pound * si::standard_gravity> {} pound_force; // https://en.wikipedia.org/wiki/Kip_(unit), -#if MP_UNITS_COMP_MSVC -inline constexpr struct kip : si::kilo_ {} kip; -#else -inline constexpr struct kip : decltype(si::kilo) {} kip; -#endif +inline constexpr auto kip = si::kilo; // pressure inline constexpr struct psi : named_unit<"psi", pound_force / square(inch)> {} psi; diff --git a/src/systems/include/mp-units/systems/natural.h b/src/systems/include/mp-units/systems/natural.h index b56ee7252..35f633396 100644 --- a/src/systems/include/mp-units/systems/natural.h +++ b/src/systems/include/mp-units/systems/natural.h @@ -39,11 +39,7 @@ namespace mp_units::natural { // clang-format off // units inline constexpr struct electronvolt : named_unit<"eV"> {} electronvolt; -#if MP_UNITS_COMP_MSVC -inline constexpr struct gigaelectronvolt : si::giga_ {} gigaelectronvolt; -#else -inline constexpr struct gigaelectronvolt : decltype(si::giga) {} gigaelectronvolt; -#endif +inline constexpr auto gigaelectronvolt = si::giga; // system references inline constexpr struct time : system_reference {} time; diff --git a/src/systems/include/mp-units/systems/si/units.h b/src/systems/include/mp-units/systems/si/units.h index 36d7772fc..72b16ba3d 100644 --- a/src/systems/include/mp-units/systems/si/units.h +++ b/src/systems/include/mp-units/systems/si/units.h @@ -41,11 +41,7 @@ namespace si { inline constexpr struct second : named_unit<"s", kind_of> {} second; inline constexpr struct metre : named_unit<"m", kind_of> {} metre; inline constexpr struct gram : named_unit<"g", kind_of> {} gram; -#if MP_UNITS_COMP_MSVC -inline constexpr struct kilogram : kilo_ {} kilogram; -#else -inline constexpr struct kilogram : decltype(kilo) {} kilogram; -#endif +inline constexpr auto kilogram = kilo; inline constexpr struct ampere : named_unit<"A", kind_of> {} ampere; inline constexpr struct absolute_zero : absolute_point_origin {} absolute_zero; @@ -107,11 +103,7 @@ inline constexpr struct degree : named_unit * degree> {} arcminute; inline constexpr struct arcsecond : named_unit * arcminute> {} arcsecond; inline constexpr struct are : named_unit<"a", square(si::deca)> {} are; -#if MP_UNITS_COMP_MSVC -inline constexpr struct hectare : si::hecto_ {} hectare; -#else -inline constexpr struct hectare : decltype(si::hecto) {} hectare; -#endif +inline constexpr auto hectare = si::hecto; inline constexpr struct litre : named_unit<"l", cubic(si::deci)> {} litre; inline constexpr struct tonne : named_unit<"t", mag<1000> * si::kilogram> {} tonne; inline constexpr struct dalton : named_unit<"Da", mag_ratio<16'605'390'666'050, 10'000'000'000'000> * mag_power<10, -27> * si::kilogram> {} dalton; diff --git a/src/systems/include/mp-units/systems/usc.h b/src/systems/include/mp-units/systems/usc.h index cfa2eb76d..87c7ace5e 100644 --- a/src/systems/include/mp-units/systems/usc.h +++ b/src/systems/include/mp-units/systems/usc.h @@ -94,7 +94,7 @@ inline constexpr struct minim : named_unit<"min", mag_ratio<1, 80> * teaspoon> { inline constexpr struct fluid_dram : named_unit<"fl dr", mag<60> * minim> {} fluid_dram; inline constexpr struct barrel : named_unit<"bbl", mag_ratio<315, 10> * gallon> {} barrel; inline constexpr struct oil_barrel : named_unit<"bbl", mag_ratio<4, 3> * barrel> {} oil_barrel; -inline constexpr struct hogshead : decltype(mag<63> * gallon) {} hogshead; +inline constexpr struct hogshead : named_unit<"hogshead", mag<63> * gallon> {} hogshead; // https://en.wikipedia.org/wiki/United_States_customary_units#Dry_volume inline constexpr struct dry_barrel : named_unit<"bbl", mag<7056> * cubic(inch)> {} dry_barrel; diff --git a/test/static/concepts_test.cpp b/test/static/concepts_test.cpp index 68033efa9..85e5a58cd 100644 --- a/test/static/concepts_test.cpp +++ b/test/static/concepts_test.cpp @@ -141,7 +141,7 @@ static_assert(!detail::QuantityKindSpec); struct metre_per_second : decltype(si::metre / si::second) {}; static_assert(Unit); -static_assert(Unit); +static_assert(Unit); static_assert(Unit)>); static_assert(Unit); static_assert(Unit); @@ -168,7 +168,7 @@ static_assert(!Unit); // NamedUnit static_assert(detail::NamedUnit); static_assert(detail::NamedUnit); -static_assert(!detail::NamedUnit); +static_assert(!detail::NamedUnit); static_assert(!detail::NamedUnit)>); static_assert(!detail::NamedUnit); static_assert(!detail::NamedUnit); @@ -194,7 +194,7 @@ static_assert(!detail::NamedUnit); // PrefixableUnit static_assert(PrefixableUnit); static_assert(PrefixableUnit); -static_assert(!PrefixableUnit); +static_assert(!PrefixableUnit); static_assert(!PrefixableUnit)>); static_assert(!PrefixableUnit); static_assert(!PrefixableUnit); @@ -220,7 +220,7 @@ static_assert(!PrefixableUnit); // AssociatedUnit static_assert(AssociatedUnit); static_assert(!AssociatedUnit); -static_assert(AssociatedUnit); +static_assert(AssociatedUnit); static_assert(AssociatedUnit)>); static_assert(AssociatedUnit); static_assert(AssociatedUnit); @@ -246,7 +246,7 @@ static_assert(!AssociatedUnit); // UnitOf static_assert(UnitOf); static_assert(UnitOf); -static_assert(UnitOf); +static_assert(UnitOf); static_assert(UnitOf); static_assert(UnitOf); static_assert(UnitOf); From 760d48502dc9f364a8bb786ba5c82842c333947b Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Wed, 5 Jun 2024 08:24:33 +0200 Subject: [PATCH 03/44] refactor: unit-related `constexpr` functions compile-time evaluation limited to only one that determines the return type --- src/core/include/mp-units/bits/sudo_cast.h | 9 +- .../include/mp-units/framework/quantity.h | 5 +- src/core/include/mp-units/framework/unit.h | 169 +++++++----------- .../mp-units/framework/unit_concepts.h | 13 +- .../include/mp-units/systems/si/chrono.h | 6 +- 5 files changed, 79 insertions(+), 123 deletions(-) diff --git a/src/core/include/mp-units/bits/sudo_cast.h b/src/core/include/mp-units/bits/sudo_cast.h index 322423b4a..ae3aa7816 100644 --- a/src/core/include/mp-units/bits/sudo_cast.h +++ b/src/core/include/mp-units/bits/sudo_cast.h @@ -64,10 +64,11 @@ template // warnings on conversions } else { // scale the number - constexpr Magnitude auto c_mag = get_canonical_unit(q_unit).mag / get_canonical_unit(To::unit).mag; - constexpr Magnitude auto num = numerator(c_mag); - constexpr Magnitude auto den = denominator(c_mag); - constexpr Magnitude auto irr = c_mag * (den / num); + constexpr Magnitude auto c_mag = + decltype(decltype(get_canonical_unit(q_unit))::mag / decltype(get_canonical_unit(To::unit))::mag){}; + constexpr Magnitude auto num = decltype(numerator(c_mag)){}; + constexpr Magnitude auto den = decltype(denominator(c_mag)){}; + constexpr Magnitude auto irr = decltype(c_mag * decltype(den / num){}){}; using c_rep_type = maybe_common_type::rep, typename To::rep>; using c_mag_type = common_magnitude_type; using multiplier_type = conditional< diff --git a/src/core/include/mp-units/framework/quantity.h b/src/core/include/mp-units/framework/quantity.h index fb63eb82c..2822ac875 100644 --- a/src/core/include/mp-units/framework/quantity.h +++ b/src/core/include/mp-units/framework/quantity.h @@ -46,8 +46,9 @@ namespace mp_units { namespace detail { template -concept IntegralConversionFactor = Unit && Unit && - is_integral(get_canonical_unit(UFrom).mag / get_canonical_unit(UTo).mag); +concept IntegralConversionFactor = + Unit && Unit && + is_integral(decltype(decltype(get_canonical_unit(UFrom))::mag / decltype(get_canonical_unit(UTo))::mag){}); template concept QuantityConvertibleTo = diff --git a/src/core/include/mp-units/framework/unit.h b/src/core/include/mp-units/framework/unit.h index 03dde4f07..c8ea6a98c 100644 --- a/src/core/include/mp-units/framework/unit.h +++ b/src/core/include/mp-units/framework/unit.h @@ -321,22 +321,12 @@ struct is_one : std::true_type {}; * @tparam U a unit to use as a `reference_unit` * @tparam M a Magnitude representing an absolute scaling factor of this unit */ -template +template struct canonical_unit { - M mag; - U reference_unit; + static constexpr auto mag = M; + static constexpr auto reference_unit = U; }; -#if MP_UNITS_COMP_CLANG - -template -canonical_unit(M, U) -> canonical_unit; - -#endif - -template -[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit&); - template [[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit&); @@ -352,64 +342,61 @@ template template [[nodiscard]] consteval auto get_canonical_unit_impl(T, const scaled_unit&) { - auto base = get_canonical_unit_impl(U{}, U{}); - return canonical_unit{M * base.mag, base.reference_unit}; -} - -template -[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit&) -{ - return canonical_unit{mag<1>, t}; + using base = decltype(get_canonical_unit_impl(U{}, U{})); + return canonical_unit{}; } template -[[nodiscard]] consteval auto get_canonical_unit_impl(T t, const named_unit&) +[[nodiscard]] consteval auto get_canonical_unit_impl(T, const named_unit&) { - return canonical_unit{mag<1>, t}; + return canonical_unit, T{}>{}; } template [[nodiscard]] consteval auto get_canonical_unit_impl(T, const named_unit&) { - return get_canonical_unit_impl(U, U); + return decltype(get_canonical_unit_impl(U, U)){}; } template [[nodiscard]] consteval auto get_canonical_unit_impl(const power&, const type_list&) { - auto mag = (mp_units::mag<1> * ... * pow(get_canonical_unit_impl(Us{}, Us{}).mag)); - auto u = (one * ... * pow(get_canonical_unit_impl(Us{}, Us{}).reference_unit)); - return canonical_unit{mag, u}; + using mag = decltype((mp_units::mag<1> * ... * pow(decltype(get_canonical_unit_impl(Us{}, Us{}))::mag))); + using u = decltype((one * ... * pow(decltype(get_canonical_unit_impl(Us{}, Us{}))::reference_unit))); + return canonical_unit{}; } template [[nodiscard]] consteval auto get_canonical_unit_impl(T, const power&) { - auto base = get_canonical_unit_impl(F{}, F{}); - if constexpr (requires { typename decltype(base.reference_unit)::_num_; }) { - auto num = get_canonical_unit_impl(power{}, typename decltype(base.reference_unit)::_num_{}); - auto den = get_canonical_unit_impl(power{}, typename decltype(base.reference_unit)::_den_{}); - return canonical_unit{pow(base.mag) * num.mag / den.mag, num.reference_unit / den.reference_unit}; + using base = decltype(get_canonical_unit_impl(F{}, F{})); + if constexpr (requires { typename decltype(base::reference_unit)::_num_; }) { + using num = + decltype(get_canonical_unit_impl(power{}, typename decltype(base::reference_unit)::_num_{})); + using den = + decltype(get_canonical_unit_impl(power{}, typename decltype(base::reference_unit)::_den_{})); + return canonical_unit(base::mag) * num::mag){} / den::mag){}, + decltype(num::reference_unit / den::reference_unit){}>{}; } else { - return canonical_unit{pow(base.mag), - derived_unit>{}}; + return canonical_unit(base::mag)){}, + derived_unit, Num, Den...>>{}>{}; } } template [[nodiscard]] consteval auto get_canonical_unit_impl(const type_list&) { - auto m = (mp_units::mag<1> * ... * get_canonical_unit_impl(Us{}, Us{}).mag); - auto u = (one * ... * get_canonical_unit_impl(Us{}, Us{}).reference_unit); - return canonical_unit{m, u}; + using m = decltype((mp_units::mag<1> * ... * decltype(get_canonical_unit_impl(Us{}, Us{}))::mag)); + using u = decltype((one * ... * decltype(get_canonical_unit_impl(Us{}, Us{}))::reference_unit)); + return canonical_unit{}; } template [[nodiscard]] consteval auto get_canonical_unit_impl(T, const derived_unit&) { - auto num = get_canonical_unit_impl(typename derived_unit::_num_{}); - auto den = get_canonical_unit_impl(typename derived_unit::_den_{}); - return canonical_unit{num.mag / den.mag, num.reference_unit / den.reference_unit}; + using num = decltype(get_canonical_unit_impl(typename derived_unit::_num_{})); + using den = decltype(get_canonical_unit_impl(typename derived_unit::_den_{})); + return canonical_unit{}; } template @@ -422,7 +409,10 @@ using type_list_of_unit_less = expr_less; // TODO this should really be in the `details` namespace but is used in `chrono.h` (a part of mp_units.systems) // Even though it is not exported, it is visible to the other module via ADL -[[nodiscard]] consteval auto get_canonical_unit(Unit auto u) { return detail::get_canonical_unit_impl(u, u); } +[[nodiscard]] consteval auto get_canonical_unit(Unit auto u) +{ + return decltype(detail::get_canonical_unit_impl(u, u)){}; +} MP_UNITS_EXPORT_BEGIN @@ -448,7 +438,7 @@ template template [[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator/(M mag, U u) { - return mag * inverse(u); + return decltype(mag * inverse(u)){}; } /** @@ -460,13 +450,13 @@ template [[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator*(Lhs lhs, Rhs rhs) { if constexpr (detail::is_specialization_of_scaled_unit && detail::is_specialization_of_scaled_unit) - return (Lhs::mag * Rhs::mag) * (Lhs::reference_unit * Rhs::reference_unit); + return decltype(Lhs::mag * Rhs::mag){} * decltype(Lhs::reference_unit * Rhs::reference_unit){}; else if constexpr (detail::is_specialization_of_scaled_unit) - return Lhs::mag * (Lhs::reference_unit * rhs); + return decltype(Lhs::mag * decltype(Lhs::reference_unit * rhs){}){}; else if constexpr (detail::is_specialization_of_scaled_unit) - return Rhs::mag * (lhs * Rhs::reference_unit); + return decltype(Rhs::mag * decltype(lhs * Rhs::reference_unit){}){}; else - return detail::expr_multiply(lhs, rhs); + return decltype(detail::expr_multiply(lhs, rhs)){}; } /** @@ -478,69 +468,36 @@ template [[nodiscard]] MP_UNITS_CONSTEVAL Unit auto operator/(Lhs lhs, Rhs rhs) { if constexpr (detail::is_specialization_of_scaled_unit && detail::is_specialization_of_scaled_unit) - return (Lhs::mag / Rhs::mag) * (Lhs::reference_unit / Rhs::reference_unit); + return decltype(Lhs::mag / Rhs::mag){} * decltype(Lhs::reference_unit / Rhs::reference_unit){}; else if constexpr (detail::is_specialization_of_scaled_unit) - return Lhs::mag * (Lhs::reference_unit / rhs); + return Lhs::mag * decltype(Lhs::reference_unit / rhs){}; else if constexpr (detail::is_specialization_of_scaled_unit) - return mag<1> / Rhs::mag * (lhs / Rhs::reference_unit); + return decltype(mag<1> / Rhs::mag){} * decltype(lhs / Rhs::reference_unit){}; else return detail::expr_divide(lhs, rhs); } -[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto inverse(Unit auto u) { return one / u; } +[[nodiscard]] MP_UNITS_CONSTEVAL Unit auto inverse(Unit auto u) { return decltype(one / u){}; } MP_UNITS_EXPORT_END namespace detail { -[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(...) { return false; } - -template -[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const named_unit&, - const named_unit&) -{ - return true; -} - -template -[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const power&, const power&) -{ - return have_same_canonical_reference_unit_impl(F1{}, F2{}); -} - -template - requires(sizeof...(Us1) == sizeof...(Us2)) -[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const type_list&, const type_list&) -{ - return (... && have_same_canonical_reference_unit_impl(Us1{}, Us2{})); -} - -template -[[nodiscard]] consteval bool have_same_canonical_reference_unit_impl(const derived_unit&, - const derived_unit&) -{ - return have_same_canonical_reference_unit_impl(typename derived_unit::_num_{}, - typename derived_unit::_num_{}) && - have_same_canonical_reference_unit_impl(typename derived_unit::_den_{}, - typename derived_unit::_den_{}); -} - -[[nodiscard]] consteval bool have_same_canonical_reference_unit(Unit auto u1, Unit auto u2) +[[nodiscard]] consteval auto have_same_canonical_reference_unit(Unit auto u1, Unit auto u2) { - auto canonical_lhs = get_canonical_unit(u1); - auto canonical_rhs = get_canonical_unit(u2); - return have_same_canonical_reference_unit_impl(canonical_lhs.reference_unit, canonical_rhs.reference_unit); + using canonical_lhs = decltype(get_canonical_unit(u1)); + using canonical_rhs = decltype(get_canonical_unit(u2)); + return std::is_same{}; } } // namespace detail -MP_UNITS_EXPORT [[nodiscard]] consteval bool operator==(Unit auto lhs, Unit auto rhs) +MP_UNITS_EXPORT template +[[nodiscard]] consteval bool operator==(U1 lhs, U2 rhs) { - auto canonical_lhs = get_canonical_unit(lhs); - auto canonical_rhs = get_canonical_unit(rhs); - return detail::have_same_canonical_reference_unit(canonical_lhs.reference_unit, canonical_rhs.reference_unit) && - canonical_lhs.mag == canonical_rhs.mag; + return decltype(detail::have_same_canonical_reference_unit(lhs, rhs))::value && + decltype(get_canonical_unit(lhs))::mag == decltype(get_canonical_unit(rhs))::mag; } namespace detail { @@ -575,7 +532,7 @@ template else if constexpr (detail::is_specialization_of_scaled_unit) return scaled_unit(U::mag), decltype(pow(U::reference_unit))>{}; else if constexpr (detail::is_specialization_of_derived_unit) - return detail::expr_pow(u); + return decltype(detail::expr_pow(u)){}; else if constexpr (Den == 1) return derived_unit>{}; else @@ -589,7 +546,7 @@ template * * @return Unit The result of computation */ -[[nodiscard]] consteval Unit auto sqrt(Unit auto u) { return pow<1, 2>(u); } +[[nodiscard]] consteval Unit auto sqrt(Unit auto u) { return decltype(pow<1, 2>(u)){}; } /** * @brief Computes the cubic root of a unit @@ -598,7 +555,7 @@ template * * @return Unit The result of computation */ -[[nodiscard]] consteval Unit auto cbrt(Unit auto u) { return pow<1, 3>(u); } +[[nodiscard]] consteval Unit auto cbrt(Unit auto u) { return decltype(pow<1, 3>(u)){}; } /** * @brief Computes the square power of a unit @@ -607,7 +564,7 @@ template * * @return Unit The result of computation */ -[[nodiscard]] consteval Unit auto square(Unit auto u) { return pow<2>(u); } +[[nodiscard]] consteval Unit auto square(Unit auto u) { return decltype(pow<2>(u)){}; } /** * @brief Computes the cubic power of a unit @@ -616,7 +573,7 @@ template * * @return Unit The result of computation */ -[[nodiscard]] consteval Unit auto cubic(Unit auto u) { return pow<3>(u); } +[[nodiscard]] consteval Unit auto cubic(Unit auto u) { return decltype(pow<3>(u)){}; } // common dimensionless units @@ -631,7 +588,7 @@ inline constexpr auto ppm = parts_per_million; // convertible_to [[nodiscard]] consteval bool convertible(Unit auto from, Unit auto to) { - return detail::have_same_canonical_reference_unit(from, to); + return decltype(detail::have_same_canonical_reference_unit(from, to))::value; } // Common unit @@ -639,7 +596,7 @@ inline constexpr auto ppm = parts_per_million; template [[nodiscard]] consteval Unit auto common_unit(U1 u1, U2 u2) - requires(detail::have_same_canonical_reference_unit(u1, u2)) + requires(decltype(detail::have_same_canonical_reference_unit(u1, u2))::value) { if constexpr (U1{} == U2{}) { if constexpr (std::derived_from) @@ -648,18 +605,18 @@ template return u2; else // TODO Check if there is a better choice here - return detail::better_type_name(u1, u2); + return decltype(detail::better_type_name(u1, u2)){}; } else { - constexpr auto canonical_lhs = get_canonical_unit(U1{}); - constexpr auto canonical_rhs = get_canonical_unit(U2{}); + using canonical_lhs = decltype(get_canonical_unit(U1{})); + using canonical_rhs = decltype(get_canonical_unit(U2{})); - if constexpr (is_integral(canonical_lhs.mag / canonical_rhs.mag)) + if constexpr (is_integral(decltype(canonical_lhs::mag / canonical_rhs::mag){})) return u2; - else if constexpr (is_integral(canonical_rhs.mag / canonical_lhs.mag)) + else if constexpr (is_integral(decltype(canonical_rhs::mag / canonical_lhs::mag){})) return u1; else { - constexpr auto cm = detail::common_magnitude(canonical_lhs.mag, canonical_rhs.mag); - return scaled_unit{}; + constexpr auto cm = decltype(detail::common_magnitude(canonical_lhs::mag, canonical_rhs::mag)){}; + return scaled_unit>{}; } } } @@ -667,7 +624,7 @@ template [[nodiscard]] consteval Unit auto common_unit(Unit auto u1, Unit auto u2, Unit auto u3, Unit auto... rest) requires requires { common_unit(common_unit(u1, u2), u3, rest...); } { - return common_unit(common_unit(u1, u2), u3, rest...); + return decltype(common_unit(common_unit(u1, u2), u3, rest...)){}; } diff --git a/src/core/include/mp-units/framework/unit_concepts.h b/src/core/include/mp-units/framework/unit_concepts.h index 02a00c7a4..bd42dc274 100644 --- a/src/core/include/mp-units/framework/unit_concepts.h +++ b/src/core/include/mp-units/framework/unit_concepts.h @@ -33,9 +33,8 @@ namespace mp_units { namespace detail { -// do not refactor below to a variable template - GCC-11 does not like it template -struct is_unit : std::false_type {}; +inline constexpr bool is_unit = false; } // namespace detail @@ -45,7 +44,7 @@ struct is_unit : std::false_type {}; * Satisfied by all unit types provided by the library. */ MP_UNITS_EXPORT template -concept Unit = detail::is_unit::value; +concept Unit = detail::is_unit; template struct scaled_unit; @@ -144,8 +143,8 @@ inline constexpr bool is_specialization_of_prefixed_unit requires requires(T* t) { is_unit_impl(t); } && (!is_specialization_of_named_unit) && - (!is_specialization_of_prefixed_unit) -struct is_unit : std::true_type {}; + (!is_specialization_of_prefixed_unit) +inline constexpr bool is_unit = true; template [[nodiscard]] consteval bool has_associated_quantity(U); @@ -197,7 +196,7 @@ concept UnitOf = namespace detail { -[[nodiscard]] consteval bool have_same_canonical_reference_unit(Unit auto u1, Unit auto u2); +[[nodiscard]] consteval auto have_same_canonical_reference_unit(Unit auto u1, Unit auto u2); } @@ -210,7 +209,7 @@ namespace detail { MP_UNITS_EXPORT template concept UnitCompatibleWith = Unit && Unit && QuantitySpec && - (!AssociatedUnit || UnitOf)&&detail::have_same_canonical_reference_unit(U{}, U2); + (!AssociatedUnit || UnitOf)&&decltype(detail::have_same_canonical_reference_unit(U{}, U2))::value; } // namespace mp_units diff --git a/src/systems/include/mp-units/systems/si/chrono.h b/src/systems/include/mp-units/systems/si/chrono.h index 2ddd71a15..6028e95c3 100644 --- a/src/systems/include/mp-units/systems/si/chrono.h +++ b/src/systems/include/mp-units/systems/si/chrono.h @@ -116,8 +116,7 @@ struct quantity_point_like_traits Q> [[nodiscard]] constexpr auto to_chrono_duration(const Q& q) { - constexpr auto canonical = get_canonical_unit(Q::unit); - constexpr detail::ratio r = detail::as_ratio(canonical.mag); + constexpr detail::ratio r = detail::as_ratio(decltype(get_canonical_unit(Q::unit))::mag); return std::chrono::duration>{q}; } @@ -127,8 +126,7 @@ template QP> { using clock = MP_UNITS_TYPENAME decltype(QP::absolute_point_origin)::clock; using rep = MP_UNITS_TYPENAME QP::rep; - constexpr auto canonical = get_canonical_unit(QP::unit); - constexpr detail::ratio r = detail::as_ratio(canonical.mag); + constexpr detail::ratio r = detail::as_ratio(decltype(get_canonical_unit(QP::unit))::mag); using ret_type = std::chrono::time_point>>; return ret_type(to_chrono_duration(qp - qp.absolute_point_origin)); } From 2876ae1ebdf120e17f4e220bf90d07e29aa92eb9 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Wed, 5 Jun 2024 08:27:48 +0200 Subject: [PATCH 04/44] build: CMake API parameter values handling and documentation improved Relates to #581 --- docs/getting_started/installation_and_usage.md | 6 +++--- src/CMakeLists.txt | 8 +++----- src/core/CMakeLists.txt | 7 +++---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/docs/getting_started/installation_and_usage.md b/docs/getting_started/installation_and_usage.md index 175bf545a..d1c4a079a 100644 --- a/docs/getting_started/installation_and_usage.md +++ b/docs/getting_started/installation_and_usage.md @@ -342,7 +342,7 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"} [`MP_UNITS_API_STD_FORMAT`](#MP_UNITS_API_STD_FORMAT){ #MP_UNITS_API_STD_FORMAT } -: [:octicons-tag-24: 2.2.0][use fmtlib support] · :octicons-milestone-24: `AUTO`/`ON`/`OFF` (Default: `AUTO`) +: [:octicons-tag-24: 2.2.0][use fmtlib support] · :octicons-milestone-24: `AUTO`/`TRUE`/`FALSE` (Default: `AUTO`) Enables the usage of [`std::format`](https://en.cppreference.com/w/cpp/utility/format/format) and associated facilities for text formatting. If it is not supported, then @@ -352,7 +352,7 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"} [`MP_UNITS_API_STRING_VIEW_RET`](#MP_UNITS_API_STRING_VIEW_RET){ #MP_UNITS_API_STRING_VIEW_RET } -: [:octicons-tag-24: 2.2.0][cmake returning string_view] · :octicons-milestone-24: `AUTO`/`ON`/`OFF` (Default: `AUTO`) +: [:octicons-tag-24: 2.2.0][cmake returning string_view] · :octicons-milestone-24: `AUTO`/`TRUE`/`FALSE` (Default: `AUTO`) Enables returning `std::string_view` from the [`unit_symbol()`](../users_guide/framework_basics/text_output.md#unit_symbol) @@ -364,7 +364,7 @@ tools.build:compiler_executables={"c": "gcc-12", "cpp": "g++-12"} [`MP_UNITS_API_NO_CRTP`](#MP_UNITS_API_NO_CRTP){ #MP_UNITS_API_NO_CRTP } -: [:octicons-tag-24: 2.2.0][cmake no crtp support] · :octicons-milestone-24: `AUTO`/`ON`/`OFF` (Default: `AUTO`) +: [:octicons-tag-24: 2.2.0][cmake no crtp support] · :octicons-milestone-24: `AUTO`/`TRUE`/`FALSE` (Default: `AUTO`) Removes the need for the usage of the CRTP idiom in the [`quantity_spec` definitions](../users_guide/framework_basics/systems_of_quantities.md#defining-quantities). diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cee2b7f17..edbaac1ed 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -85,7 +85,7 @@ check_cxx_feature_supported(__cpp_explicit_this_parameter ${projectPrefix}EXPLIC # validate settings if(NOT ${projectPrefix}API_FREESTANDING - AND ${projectPrefix}API_STD_FORMAT STREQUAL "TRUE" + AND "${projectPrefix}API_STD_FORMAT" AND NOT (${projectPrefix}LIB_FORMAT_SUPPORTED # libc++ has a basic supports for std::format but does not set __cpp_lib_format @@ -96,13 +96,11 @@ if(NOT ${projectPrefix}API_FREESTANDING message(FATAL_ERROR "`std::format` enabled but not supported") endif() -if(${projectPrefix}API_STRING_VIEW_RET STREQUAL "TRUE" AND NOT - ${projectPrefix}STATIC_CONSTEXPR_VARS_IN_CONSTEXPR_FUNCTIONS -) +if("${projectPrefix}API_STRING_VIEW_RET" AND NOT ${projectPrefix}STATIC_CONSTEXPR_VARS_IN_CONSTEXPR_FUNCTIONS) message(FATAL_ERROR "`std::string_view` returns enabled but not supported") endif() -if(${projectPrefix}API_NO_CRTP STREQUAL "TRUE" AND NOT ${projectPrefix}EXPLICIT_THIS_PARAMETER_SUPPORTED) +if("${projectPrefix}API_NO_CRTP" AND NOT ${projectPrefix}EXPLICIT_THIS_PARAMETER_SUPPORTED) message(FATAL_ERROR "`NO_CRTP` mode enabled but explicit `this` parameter is not supported") endif() diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9d2839f30..45c91dd01 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -23,8 +23,7 @@ cmake_minimum_required(VERSION 3.23) function(set_feature_flag name) - set(val_list "TRUE" "FALSE") - if(${projectPrefix}${name} IN_LIST val_list) + if(NOT ${projectPrefix}${name} STREQUAL "AUTO") target_compile_definitions( mp-units-core ${${projectPrefix}TARGET_SCOPE} ${projectPrefix}${name}=$ ) @@ -99,8 +98,8 @@ set_feature_flag(API_NO_CRTP) # Text formatting if(NOT ${projectPrefix}API_FREESTANDING - AND (${projectPrefix}API_STD_FORMAT STREQUAL "FALSE" OR (${projectPrefix}API_STD_FORMAT STREQUAL "AUTO" - AND NOT ${projectPrefix}LIB_FORMAT_SUPPORTED)) + AND (NOT ${projectPrefix}API_STD_FORMAT OR (${projectPrefix}API_STD_FORMAT STREQUAL "AUTO" + AND NOT ${projectPrefix}LIB_FORMAT_SUPPORTED)) ) if(NOT TARGET fmt::fmt) find_package(fmt REQUIRED) From 4aea85656b0dc8127fa254062ae459f9ec3c440a Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Thu, 6 Jun 2024 13:16:13 +0200 Subject: [PATCH 05/44] refactor: units no longer inherit from each other --- src/core/include/mp-units/framework/unit.h | 61 ++++++++++++------- .../mp-units/framework/unit_concepts.h | 7 +++ test/static/concepts_test.cpp | 22 +++---- test/static/reference_test.cpp | 10 +-- 4 files changed, 59 insertions(+), 41 deletions(-) diff --git a/src/core/include/mp-units/framework/unit.h b/src/core/include/mp-units/framework/unit.h index c8ea6a98c..7d5a7f07b 100644 --- a/src/core/include/mp-units/framework/unit.h +++ b/src/core/include/mp-units/framework/unit.h @@ -62,6 +62,13 @@ struct propagate_point_origin { static constexpr auto point_origin = U::point_origin; }; +template +struct scaled_unit_impl : detail::propagate_point_origin { + using _base_type_ = scaled_unit_impl; // exposition only + static constexpr MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(Magnitude) auto mag = M; + static constexpr U reference_unit{}; +}; + } // namespace detail /** @@ -74,10 +81,7 @@ struct propagate_point_origin { * instantiate this type automatically based on the unit arithmetic equation provided by the user. */ template -struct scaled_unit : detail::propagate_point_origin { - static constexpr MP_UNITS_CONSTRAINED_AUTO_WORKAROUND(Magnitude) auto mag = M; - static constexpr U reference_unit{}; -}; +struct scaled_unit final : detail::scaled_unit_impl {}; namespace detail { @@ -137,6 +141,7 @@ struct named_unit; template requires(!Symbol.empty()) && detail::BaseDimension> struct named_unit { + using _base_type_ = named_unit; // exposition only static constexpr auto symbol = Symbol; ///< Unique base unit identifier static constexpr auto quantity_spec = QS; }; @@ -144,6 +149,7 @@ struct named_unit { template requires(!Symbol.empty()) && detail::BaseDimension> struct named_unit { + using _base_type_ = named_unit; // exposition only static constexpr auto symbol = Symbol; ///< Unique base unit identifier static constexpr auto quantity_spec = QS; static constexpr auto point_origin = PO; @@ -162,6 +168,7 @@ struct named_unit { template requires(!Symbol.empty()) struct named_unit { + using _base_type_ = named_unit; // exposition only static constexpr auto symbol = Symbol; ///< Unique base unit identifier }; @@ -175,13 +182,15 @@ struct named_unit { */ template requires(!Symbol.empty()) -struct named_unit : decltype(U) { +struct named_unit : decltype(U)::_base_type_ { + using _base_type_ = named_unit; // exposition only static constexpr auto symbol = Symbol; ///< Unique unit identifier }; template requires(!Symbol.empty()) -struct named_unit : decltype(U) { +struct named_unit : decltype(U)::_base_type_ { + using _base_type_ = named_unit; // exposition only static constexpr auto symbol = Symbol; ///< Unique unit identifier static constexpr auto point_origin = PO; }; @@ -197,14 +206,16 @@ struct named_unit : decltype(U) { */ template requires(!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension) -struct named_unit : decltype(U) { +struct named_unit : decltype(U)::_base_type_ { + using _base_type_ = named_unit; // exposition only static constexpr auto symbol = Symbol; ///< Unique unit identifier static constexpr auto quantity_spec = QS; }; template requires(!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension) -struct named_unit : decltype(U) { +struct named_unit : decltype(U)::_base_type_ { + using _base_type_ = named_unit; // exposition only static constexpr auto symbol = Symbol; ///< Unique unit identifier static constexpr auto quantity_spec = QS; static constexpr auto point_origin = PO; @@ -234,7 +245,8 @@ struct named_unit : decltype(U) { */ MP_UNITS_EXPORT template requires(!Symbol.empty()) -struct prefixed_unit : decltype(M * U) { +struct prefixed_unit : decltype(M * U)::_base_type_ { + using _base_type_ = prefixed_unit; // exposition only static constexpr auto symbol = Symbol + U.symbol; }; @@ -243,6 +255,11 @@ namespace detail { template struct is_one : std::false_type {}; +template +struct derived_unit_impl : detail::expr_fractions { + using _base_type_ = derived_unit_impl; // exposition only +}; + } // namespace detail /** @@ -291,7 +308,7 @@ struct is_one : std::false_type {}; * instantiate this type automatically based on the unit arithmetic equation provided by the user. */ template -struct derived_unit : detail::expr_fractions {}; +struct derived_unit : detail::derived_unit_impl {}; /** * @brief Unit one @@ -299,7 +316,7 @@ struct derived_unit : detail::expr_fractions {}; * Unit of a dimensionless quantity. */ // clang-format off -MP_UNITS_EXPORT inline constexpr struct one : derived_unit<> {} one; +MP_UNITS_EXPORT inline constexpr struct one : detail::derived_unit_impl<> {} one; // clang-format on namespace detail { @@ -337,10 +354,10 @@ template [[nodiscard]] consteval auto get_canonical_unit_impl(T, const power&); template -[[nodiscard]] consteval auto get_canonical_unit_impl(T, const derived_unit&); +[[nodiscard]] consteval auto get_canonical_unit_impl(T, const derived_unit_impl&); template -[[nodiscard]] consteval auto get_canonical_unit_impl(T, const scaled_unit&) +[[nodiscard]] consteval auto get_canonical_unit_impl(T, const scaled_unit_impl&) { using base = decltype(get_canonical_unit_impl(U{}, U{})); return canonical_unit{}; @@ -392,10 +409,10 @@ template } template -[[nodiscard]] consteval auto get_canonical_unit_impl(T, const derived_unit&) +[[nodiscard]] consteval auto get_canonical_unit_impl(T, const derived_unit_impl&) { - using num = decltype(get_canonical_unit_impl(typename derived_unit::_num_{})); - using den = decltype(get_canonical_unit_impl(typename derived_unit::_den_{})); + using num = decltype(get_canonical_unit_impl(typename derived_unit_impl::_num_{})); + using den = decltype(get_canonical_unit_impl(typename derived_unit_impl::_den_{})); return canonical_unit{}; } @@ -599,9 +616,9 @@ template requires(decltype(detail::have_same_canonical_reference_unit(u1, u2))::value) { if constexpr (U1{} == U2{}) { - if constexpr (std::derived_from) + if constexpr (std::derived_from) return u1; - else if constexpr (std::derived_from) + else if constexpr (std::derived_from) return u2; else // TODO Check if there is a better choice here @@ -695,7 +712,7 @@ constexpr Out unit_symbol_impl(Out out, U, const unit_symbol_formatting& fmt, bo } template Out, auto M, typename U> -constexpr Out unit_symbol_impl(Out out, const scaled_unit& u, const unit_symbol_formatting& fmt, +constexpr Out unit_symbol_impl(Out out, const scaled_unit_impl& u, const unit_symbol_formatting& fmt, bool negative_power) { if constexpr (M == mag<1>) { @@ -764,13 +781,13 @@ constexpr Out unit_symbol_impl(Out out, const type_list& nums, const ty } template Out, typename... Expr> -constexpr Out unit_symbol_impl(Out out, const derived_unit&, const unit_symbol_formatting& fmt, +constexpr Out unit_symbol_impl(Out out, const derived_unit_impl&, const unit_symbol_formatting& fmt, bool negative_power) { (void)negative_power; MP_UNITS_EXPECTS(negative_power == false); - return unit_symbol_impl(out, typename derived_unit::_num_{}, typename derived_unit::_den_{}, - fmt); + return unit_symbol_impl(out, typename derived_unit_impl::_num_{}, + typename derived_unit_impl::_den_{}, fmt); } } // namespace detail diff --git a/src/core/include/mp-units/framework/unit_concepts.h b/src/core/include/mp-units/framework/unit_concepts.h index bd42dc274..cbc9abf3e 100644 --- a/src/core/include/mp-units/framework/unit_concepts.h +++ b/src/core/include/mp-units/framework/unit_concepts.h @@ -52,6 +52,8 @@ struct scaled_unit; MP_UNITS_EXPORT template struct named_unit; +MP_UNITS_EXPORT struct one; + namespace detail { template @@ -126,9 +128,14 @@ void is_unit_impl(const scaled_unit*); template void is_unit_impl(const named_unit*); +template +void is_unit_impl(const prefixed_unit*); + template void is_unit_impl(const derived_unit*); +void is_unit_impl(const one*); + template inline constexpr bool is_specialization_of_unit = false; diff --git a/test/static/concepts_test.cpp b/test/static/concepts_test.cpp index 85e5a58cd..33fd85a5a 100644 --- a/test/static/concepts_test.cpp +++ b/test/static/concepts_test.cpp @@ -138,8 +138,6 @@ static_assert(!detail::QuantityKindSpec); // TODO add tests // Unit -struct metre_per_second : decltype(si::metre / si::second) {}; - static_assert(Unit); static_assert(Unit); static_assert(Unit)>); @@ -151,13 +149,12 @@ static_assert(Unit); static_assert(Unit(si::metre))>); static_assert(Unit); static_assert(Unit, struct si::second>>); -static_assert(Unit); static_assert(Unit>>); static_assert(Unit); -static_assert(!Unit>); +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); @@ -177,13 +174,12 @@ static_assert(!detail::NamedUnit); static_assert(!detail::NamedUnit(si::metre))>); static_assert(detail::NamedUnit); static_assert(!detail::NamedUnit, struct si::second>>); -static_assert(!detail::NamedUnit); static_assert(!detail::NamedUnit>>); static_assert(!detail::NamedUnit); -static_assert(!detail::NamedUnit>); +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); @@ -203,13 +199,12 @@ static_assert(!PrefixableUnit); static_assert(!PrefixableUnit(si::metre))>); static_assert(PrefixableUnit); static_assert(!PrefixableUnit, struct si::second>>); -static_assert(!PrefixableUnit); static_assert(!PrefixableUnit>>); static_assert(!PrefixableUnit); -static_assert(!PrefixableUnit>); +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); @@ -229,13 +224,12 @@ static_assert(AssociatedUnit); static_assert(AssociatedUnit(si::metre))>); static_assert(AssociatedUnit); static_assert(AssociatedUnit, struct si::second>>); -static_assert(AssociatedUnit); static_assert(AssociatedUnit>>); static_assert(AssociatedUnit); -static_assert(!AssociatedUnit>); +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/static/reference_test.cpp b/test/static/reference_test.cpp index df9285055..58e2611df 100644 --- a/test/static/reference_test.cpp +++ b/test/static/reference_test.cpp @@ -192,7 +192,7 @@ static_assert(is_of_type<2 * m_per_s, quantity>, derived_unit>>{}, int>>); + quantity>, derived_unit)>, per>>{}, int>>); static_assert(120 * length[kilometre] / (2 * time[hour]) == 60 * speed[kilometre / hour]); static_assert( is_of_type< @@ -201,14 +201,14 @@ static_assert( const auto duration = 2; return distance * length[kilometre] / (duration * time[hour]); }(), - quantity>, derived_unit>>{}, int>>); + quantity>, derived_unit)>, per>>{}, int>>); static_assert( is_of_type>, derived_unit>>{}, + quantity>, derived_unit)>, per>>{}, std::int64_t>>); static_assert( is_of_type<120.L * length[kilometre] / (2 * time[hour]), - quantity>, derived_unit>>{}, + quantity>, derived_unit)>, per>>{}, long double>>); static_assert(is_of_type<1. / 4 * area[square(metre)], decltype(1. * area[square(metre)] / 4)>); @@ -226,7 +226,7 @@ static_assert(is_of_type<42 * nu::length[nu::second] / (42 * nu::time[nu::second static_assert(is_of_type<42 * nu::speed[nu::second / nu::second], quantity{}, int>>); static_assert(is_of_type<42 * nu::speed[one], quantity{}, int>>); static_assert(is_of_type<42 * mass[kilogram] * (1 * nu::length[nu::second]) / (1 * nu::time[nu::second]), - quantity>, kilogram_>{}, int>>); + quantity>, std::remove_const_t)>>{}, int>>); template concept invalid_nu_unit = !requires { dim[unit]; }; From c69bd140b201f92d46407a7237416923a909734e Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Thu, 6 Jun 2024 13:18:45 +0200 Subject: [PATCH 06/44] refactor: all units made `final` --- .../framework_basics/design_overview.md | 12 +- .../dimensionless_quantities.md | 14 +-- .../faster_than_lightspeed_constants.md | 4 +- .../interface_introduction.md | 10 +- .../framework_basics/systems_of_units.md | 20 ++-- .../framework_basics/text_output.md | 36 +++--- .../framework_basics/the_affine_space.md | 6 +- .../framework_basics/value_conversions.md | 12 +- example/currency.cpp | 8 +- .../mp-units/framework/system_reference.h | 8 +- src/core/include/mp-units/framework/unit.h | 24 ++-- .../include/mp-units/systems/angular/units.h | 10 +- src/systems/include/mp-units/systems/cgs.h | 14 +-- src/systems/include/mp-units/systems/hep.h | 8 +- src/systems/include/mp-units/systems/iau.h | 26 ++--- .../systems/iec80000/binary_prefixes.h | 16 +-- .../include/mp-units/systems/iec80000/units.h | 10 +- .../include/mp-units/systems/imperial.h | 42 +++---- .../include/mp-units/systems/international.h | 40 +++---- .../include/mp-units/systems/natural.h | 2 +- .../include/mp-units/systems/si/constants.h | 18 +-- .../include/mp-units/systems/si/prefixes.h | 48 ++++---- .../include/mp-units/systems/si/units.h | 84 +++++++------- .../include/mp-units/systems/typographic.h | 8 +- src/systems/include/mp-units/systems/usc.h | 92 ++++++++-------- test/runtime/truncation_test.cpp | 2 +- test/static/dimension_test.cpp | 2 +- test/static/quantity_point_test.cpp | 2 +- test/static/quantity_spec_test.cpp | 2 +- test/static/reference_test.cpp | 38 +++---- test/static/unit_test.cpp | 104 +++++++++--------- 31 files changed, 364 insertions(+), 358 deletions(-) diff --git a/docs/users_guide/framework_basics/design_overview.md b/docs/users_guide/framework_basics/design_overview.md index da38cd955..8513ee806 100644 --- a/docs/users_guide/framework_basics/design_overview.md +++ b/docs/users_guide/framework_basics/design_overview.md @@ -234,13 +234,13 @@ A unit can be defined by the user in one of the following ways: template struct kilo_ : prefixed_unit<"k", mag_power<10, 3>, U{}> {}; template inline constexpr kilo_ kilo; -inline constexpr struct second : named_unit<"s", kind_of> {} second; -inline constexpr struct minute : named_unit<"min", mag<60> * second> {} minute; -inline constexpr struct gram : named_unit<"g", kind_of> {} gram; -inline constexpr struct kilogram : decltype(kilo) {} kilogram; -inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton; +inline constexpr struct second final : named_unit<"s", kind_of> {} second; +inline constexpr struct minute final : named_unit<"min", mag<60> * second> {} minute; +inline constexpr struct gram final : named_unit<"g", kind_of> {} gram; +inline constexpr auto kilogram = kilo; +inline constexpr struct newton final : named_unit<"N", kilogram * metre / square(second)> {} newton; -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 speed_of_light_in_vacuum final : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum; ``` The [unit equation](../../appendix/glossary.md#unit-equation) of `si::metre / si::second` results diff --git a/docs/users_guide/framework_basics/dimensionless_quantities.md b/docs/users_guide/framework_basics/dimensionless_quantities.md index 3019828fe..05bbca18c 100644 --- a/docs/users_guide/framework_basics/dimensionless_quantities.md +++ b/docs/users_guide/framework_basics/dimensionless_quantities.md @@ -113,7 +113,7 @@ that uses a unit that is proportional to the ratio of kilometers per megaparsecs units of _length_: ```cpp -inline constexpr struct hubble_constant : +inline constexpr struct hubble_constant final : named_unit<{u8"H₀", "H_0"}, mag_ratio<701, 10> * si::kilo / si::second / si::mega> {} hubble_constant; ``` @@ -158,9 +158,9 @@ Besides the unit `one`, there are a few other scaled units predefined in the lib with dimensionless quantities: ```cpp -inline constexpr struct percent : named_unit<"%", mag_ratio<1, 100> * one> {} percent; -inline constexpr struct per_mille : named_unit<{u8"‰", "%o"}, mag_ratio<1, 1000> * one> {} per_mille; -inline constexpr struct parts_per_million : named_unit<"ppm", mag_ratio<1, 1'000'000> * one> {} parts_per_million; +inline constexpr struct percent final : named_unit<"%", mag_ratio<1, 100> * one> {} percent; +inline constexpr struct per_mille final : named_unit<{u8"‰", "%o"}, mag_ratio<1, 1000> * one> {} per_mille; +inline constexpr struct parts_per_million final : named_unit<"ppm", mag_ratio<1, 1'000'000> * one> {} parts_per_million; inline constexpr auto ppm = parts_per_million; ``` @@ -242,9 +242,9 @@ With the above, we can constrain `radian`, `steradian`, and `bit` to be allowed specific quantity kinds only: ```cpp -inline constexpr struct radian : named_unit<"rad", metre / metre, kind_of> {} radian; -inline constexpr struct steradian : named_unit<"sr", square(metre) / square(metre), kind_of> {} steradian; -inline constexpr struct bit : named_unit<"bit", one, kind_of> {} bit; +inline constexpr struct radian final : named_unit<"rad", metre / metre, kind_of> {} radian; +inline constexpr struct steradian final : named_unit<"sr", square(metre) / square(metre), kind_of> {} steradian; +inline constexpr struct bit final : named_unit<"bit", one, kind_of> {} bit; ``` but still allow the usage of `one` and its scaled versions for such quantities. diff --git a/docs/users_guide/framework_basics/faster_than_lightspeed_constants.md b/docs/users_guide/framework_basics/faster_than_lightspeed_constants.md index d69ef39c1..cef490db0 100644 --- a/docs/users_guide/framework_basics/faster_than_lightspeed_constants.md +++ b/docs/users_guide/framework_basics/faster_than_lightspeed_constants.md @@ -39,12 +39,12 @@ namespace si { namespace si2019 { -inline constexpr struct speed_of_light_in_vacuum : +inline constexpr struct speed_of_light_in_vacuum final : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum; } // namespace si2019 -inline constexpr struct magnetic_constant : +inline constexpr struct magnetic_constant final : named_unit<{u8"μ₀", "u_0"}, mag<4> * mag_pi * mag_power<10, -7> * henry / metre> {} magnetic_constant; } // namespace mp_units::si diff --git a/docs/users_guide/framework_basics/interface_introduction.md b/docs/users_guide/framework_basics/interface_introduction.md index f1bcc16fe..9f3de85c6 100644 --- a/docs/users_guide/framework_basics/interface_introduction.md +++ b/docs/users_guide/framework_basics/interface_introduction.md @@ -6,8 +6,8 @@ The **mp-units** library decided to use a rather unusual pattern to define entit Here is how we define `metre` and `second` [SI](../../appendix/glossary.md#si) base units: ```cpp -inline constexpr struct metre : named_unit<"m", kind_of> {} metre; -inline constexpr struct second : named_unit<"s", kind_of> {} second; +inline constexpr struct metre final : named_unit<"m", kind_of> {} metre; +inline constexpr struct second final : named_unit<"s", kind_of> {} second; ``` Please note that the above reuses the same identifier for a type and its value. The rationale @@ -94,9 +94,9 @@ the value-based [unit equation](../../appendix/glossary.md#unit-equation) to a c definition: ```cpp -inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton; -inline constexpr struct pascal : named_unit<"Pa", newton / square(metre)> {} pascal; -inline constexpr struct joule : named_unit<"J", newton * metre> {} joule; +inline constexpr struct newton final : named_unit<"N", kilogram * metre / square(second)> {} newton; +inline constexpr struct pascal final : named_unit<"Pa", newton / square(metre)> {} pascal; +inline constexpr struct joule final : named_unit<"J", newton * metre> {} joule; ``` diff --git a/docs/users_guide/framework_basics/systems_of_units.md b/docs/users_guide/framework_basics/systems_of_units.md index 3d263c112..df37b6bf4 100644 --- a/docs/users_guide/framework_basics/systems_of_units.md +++ b/docs/users_guide/framework_basics/systems_of_units.md @@ -26,7 +26,7 @@ this is expressed by associating a quantity kind (that we discussed in detail in previous chapter) with a unit that is used to express it: ```cpp -inline constexpr struct metre : named_unit<"m", kind_of> {} metre; +inline constexpr struct metre final : named_unit<"m", kind_of> {} metre; ``` !!! important @@ -67,7 +67,7 @@ of a specific predefined [unit equation](../../appendix/glossary.md#unit-equatio For example, a unit of _power_ quantity is defined in the library as: ```cpp -inline constexpr struct watt : named_unit<"W", joule / second> {} watt; +inline constexpr struct watt final : named_unit<"W", joule / second> {} watt; ``` However, a _power_ quantity can be expressed in other units as well. For example, @@ -110,8 +110,8 @@ The library allows constraining such units to work only with quantities of a spe the following way: ```cpp -inline constexpr struct hertz : named_unit<"Hz", one / second, kind_of> {} hertz; -inline constexpr struct becquerel : named_unit<"Bq", one / second, kind_of> {} becquerel; +inline constexpr struct hertz final : named_unit<"Hz", one / second, kind_of> {} hertz; +inline constexpr struct becquerel final : named_unit<"Bq", one / second, kind_of> {} becquerel; ``` With the above, `hertz` can only be used with _frequencies_, while `becquerel` should only be used with @@ -168,25 +168,25 @@ be explicitly expressed with predefined SI prefixes. Those include units like mi electronvolt: ```cpp -inline constexpr struct minute : named_unit<"min", mag<60> * si::second> {} minute; -inline constexpr struct hour : named_unit<"h", mag<60> * minute> {} hour; -inline constexpr struct electronvolt : named_unit<"eV", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * si::joule> {} electronvolt; +inline constexpr struct minute final : named_unit<"min", mag<60> * si::second> {} minute; +inline constexpr struct hour final : named_unit<"h", mag<60> * minute> {} hour; +inline constexpr struct electronvolt final : named_unit<"eV", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * si::joule> {} electronvolt; ``` Also, units of other [systems of units](../../appendix/glossary.md#system-of-units) are often defined in terms of scaled versions of the SI units. For example, the international yard is defined as: ```cpp -inline constexpr struct yard : named_unit<"yd", mag_ratio<9'144, 10'000> * si::metre> {} yard; +inline constexpr struct yard final : named_unit<"yd", mag_ratio<9'144, 10'000> * si::metre> {} yard; ``` For some units, a magnitude might also be irrational. The best example here is a `degree` which is defined using a floating-point magnitude having a factor of the number π (Pi): ```cpp -inline constexpr struct mag_pi : magnitude> {} mag_pi; +inline constexpr struct mag_pi final : magnitude> {} mag_pi; ``` ```cpp -inline constexpr struct degree : named_unit<{u8"°", "deg"}, mag_pi / mag<180> * si::radian> {} degree; +inline constexpr struct degree final : named_unit<{u8"°", "deg"}, mag_pi / mag<180> * si::radian> {} degree; ``` diff --git a/docs/users_guide/framework_basics/text_output.md b/docs/users_guide/framework_basics/text_output.md index 67bd4395d..6487640e2 100644 --- a/docs/users_guide/framework_basics/text_output.md +++ b/docs/users_guide/framework_basics/text_output.md @@ -45,18 +45,18 @@ and units of derived quantities. === "Units" ```cpp - inline constexpr struct second : named_unit<"s", kind_of> {} second; - inline constexpr struct metre : named_unit<"m", kind_of> {} metre; - inline constexpr struct gram : named_unit<"g", kind_of> {} gram; + inline constexpr struct second final : named_unit<"s", kind_of> {} second; + inline constexpr struct metre final : named_unit<"m", kind_of> {} metre; + inline constexpr struct gram final : named_unit<"g", kind_of> {} gram; inline constexpr auto kilogram = kilo; - inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton; - inline constexpr struct joule : named_unit<"J", newton * metre> {} joule; - inline constexpr struct watt : named_unit<"W", joule / second> {} watt; - inline constexpr struct coulomb : named_unit<"C", ampere * second> {} coulomb; - inline constexpr struct volt : named_unit<"V", watt / ampere> {} volt; - inline constexpr struct farad : named_unit<"F", coulomb / volt> {} farad; - inline constexpr struct ohm : named_unit<{u8"Ω", "ohm"}, volt / ampere> {} ohm; + inline constexpr struct newton final : named_unit<"N", kilogram * metre / square(second)> {} newton; + inline constexpr struct joule final : named_unit<"J", newton * metre> {} joule; + inline constexpr struct watt final : named_unit<"W", joule / second> {} watt; + inline constexpr struct coulomb final : named_unit<"C", ampere * second> {} coulomb; + inline constexpr struct volt final : named_unit<"V", watt / ampere> {} volt; + inline constexpr struct farad final : named_unit<"F", coulomb / volt> {} farad; + inline constexpr struct ohm final : named_unit<{u8"Ω", "ohm"}, volt / ampere> {} ohm; ``` === "Prefixes" @@ -75,13 +75,13 @@ and units of derived quantities. === "Constants" ```cpp - inline constexpr struct hyperfine_structure_transition_frequency_of_cs : named_unit<{u8"Δν_Cs", "dv_Cs"}, mag<9'192'631'770> * 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_ratio<662'607'015, 100'000'000> * mag_power<10, -34> * joule * second> {} planck_constant; - inline constexpr struct elementary_charge : named_unit<"e", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * coulomb> {} elementary_charge; - inline constexpr struct boltzmann_constant : named_unit<"k", mag_ratio<1'380'649, 1'000'000> * mag_power<10, -23> * joule / kelvin> {} boltzmann_constant; - inline constexpr struct avogadro_constant : named_unit<"N_A", mag_ratio<602'214'076, 100'000'000> * mag_power<10, 23> / mole> {} avogadro_constant; - inline constexpr struct luminous_efficacy : named_unit<"K_cd", mag<683> * lumen / watt> {} luminous_efficacy; + inline constexpr struct hyperfine_structure_transition_frequency_of_cs final : named_unit<{u8"Δν_Cs", "dv_Cs"}, mag<9'192'631'770> * hertz> {} hyperfine_structure_transition_frequency_of_cs; + inline constexpr struct speed_of_light_in_vacuum final : named_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum; + inline constexpr struct planck_constant final : named_unit<"h", mag_ratio<662'607'015, 100'000'000> * mag_power<10, -34> * joule * second> {} planck_constant; + inline constexpr struct elementary_charge final : named_unit<"e", mag_ratio<1'602'176'634, 1'000'000'000> * mag_power<10, -19> * coulomb> {} elementary_charge; + inline constexpr struct boltzmann_constant final : named_unit<"k", mag_ratio<1'380'649, 1'000'000> * mag_power<10, -23> * joule / kelvin> {} boltzmann_constant; + inline constexpr struct avogadro_constant final : named_unit<"N_A", mag_ratio<602'214'076, 100'000'000> * mag_power<10, 23> / mole> {} avogadro_constant; + inline constexpr struct luminous_efficacy final : named_unit<"K_cd", mag<683> * lumen / watt> {} luminous_efficacy; ``` !!! important @@ -105,7 +105,7 @@ and units of derived quantities. template name to initialize it with two symbols: ```cpp - inline constexpr struct ohm : named_unit {} ohm; + inline constexpr struct ohm final : named_unit {} ohm; ``` diff --git a/docs/users_guide/framework_basics/the_affine_space.md b/docs/users_guide/framework_basics/the_affine_space.md index c21bceea9..5ed28660b 100644 --- a/docs/users_guide/framework_basics/the_affine_space.md +++ b/docs/users_guide/framework_basics/the_affine_space.md @@ -426,16 +426,16 @@ definitions: ```cpp namespace si { -inline constexpr struct kelvin : +inline constexpr struct kelvin final : named_unit<"K", kind_of, zeroth_kelvin> {} kelvin; -inline constexpr struct degree_Celsius : +inline constexpr struct degree_Celsius final : named_unit<{u8"°C", "`C"}, kelvin, zeroth_degree_Celsius> {} degree_Celsius; } namespace usc { -inline constexpr struct degree_Fahrenheit : +inline constexpr struct degree_Fahrenheit final : named_unit<{u8"°F", "`F"}, mag_ratio<5, 9> * si::degree_Celsius, zeroth_degree_Fahrenheit> {} degree_Fahrenheit; diff --git a/docs/users_guide/framework_basics/value_conversions.md b/docs/users_guide/framework_basics/value_conversions.md index bed6e9288..ecc6d6c91 100644 --- a/docs/users_guide/framework_basics/value_conversions.md +++ b/docs/users_guide/framework_basics/value_conversions.md @@ -88,8 +88,8 @@ the `value_cast(q)` which always returns the most precise result: inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency; inline constexpr struct currency : quantity_spec {} currency; - inline constexpr struct us_dollar : named_unit<"USD", kind_of> {} us_dollar; - inline constexpr struct scaled_us_dollar : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar; + inline constexpr struct us_dollar final : named_unit<"USD", kind_of> {} us_dollar; + inline constexpr struct scaled_us_dollar final : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar; namespace unit_symbols { @@ -108,8 +108,8 @@ the `value_cast(q)` which always returns the most precise result: inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency; inline constexpr struct currency : quantity_spec {} currency; - inline constexpr struct us_dollar : named_unit<"USD", kind_of> {} us_dollar; - inline constexpr struct scaled_us_dollar : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar; + inline constexpr struct us_dollar final : named_unit<"USD", kind_of> {} us_dollar; + inline constexpr struct scaled_us_dollar final : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar; namespace unit_symbols { @@ -128,8 +128,8 @@ the `value_cast(q)` which always returns the most precise result: inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency; QUANTITY_SPEC(currency, dim_currency); - inline constexpr struct us_dollar : named_unit<"USD", kind_of> {} us_dollar; - inline constexpr struct scaled_us_dollar : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar; + inline constexpr struct us_dollar final : named_unit<"USD", kind_of> {} us_dollar; + inline constexpr struct scaled_us_dollar final : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar; namespace unit_symbols { diff --git a/example/currency.cpp b/example/currency.cpp index a638fe864..bbbb55cfd 100644 --- a/example/currency.cpp +++ b/example/currency.cpp @@ -40,10 +40,10 @@ inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency; QUANTITY_SPEC(currency, dim_currency); -inline constexpr struct euro : named_unit<"EUR", kind_of> {} euro; -inline constexpr struct us_dollar : named_unit<"USD", kind_of> {} us_dollar; -inline constexpr struct great_british_pound : named_unit<"GBP", kind_of> {} great_british_pound; -inline constexpr struct japanese_jen : named_unit<"JPY", kind_of> {} japanese_jen; +inline constexpr struct euro final : named_unit<"EUR", kind_of> {} euro; +inline constexpr struct us_dollar final : named_unit<"USD", kind_of> {} us_dollar; +inline constexpr struct great_british_pound final : named_unit<"GBP", kind_of> {} great_british_pound; +inline constexpr struct japanese_jen final : named_unit<"JPY", kind_of> {} japanese_jen; // clang-format on namespace unit_symbols { diff --git a/src/core/include/mp-units/framework/system_reference.h b/src/core/include/mp-units/framework/system_reference.h index b4c202ecf..5718cb1ac 100644 --- a/src/core/include/mp-units/framework/system_reference.h +++ b/src/core/include/mp-units/framework/system_reference.h @@ -45,10 +45,10 @@ namespace mp_units { * @code{.cpp} * // hypothetical natural system of units for c=1 * - * inline constexpr struct second : named_unit<"s"> {} second; - * inline constexpr struct minute : named_unit<"min", mag<60> * second> {} minute; - * inline constexpr struct gram : named_unit<"g"> {} gram; - * inline constexpr struct kilogram : decltype(si::kilo) {} kilogram; + * inline constexpr struct second final : named_unit<"s"> {} second; + * inline constexpr struct minute final : named_unit<"min", mag<60> * second> {} minute; + * inline constexpr struct gram final : named_unit<"g"> {} gram; + * inline constexpr auto kilogram = si::kilo; * * inline constexpr struct time : system_reference {} time; * inline constexpr struct length : system_reference {} length; diff --git a/src/core/include/mp-units/framework/unit.h b/src/core/include/mp-units/framework/unit.h index 7d5a7f07b..5cc51d636 100644 --- a/src/core/include/mp-units/framework/unit.h +++ b/src/core/include/mp-units/framework/unit.h @@ -104,12 +104,12 @@ inline constexpr bool is_specialization_of_scaled_unit> = true * For example: * * @code{.cpp} - * inline constexpr struct second : named_unit<"s", time> {} second; - * inline constexpr struct metre : named_unit<"m", length> {} metre; - * inline constexpr struct hertz : named_unit<"Hz", inverse(second)> {} hertz; - * inline constexpr struct newton : named_unit<"N", kilogram * metre / square(second)> {} newton; - * inline constexpr struct degree_Celsius : named_unit<{u8"°C", "`C"}, kelvin> {} degree_Celsius; - * inline constexpr struct minute : named_unit<"min", mag<60> * second> {} minute; + * inline constexpr struct second final : named_unit<"s", kind_of