From 6aa848a4568bf72ffb856544ca4d1f269bd2e7f8 Mon Sep 17 00:00:00 2001 From: Mateusz Pusz Date: Wed, 12 Jun 2024 14:17:32 +0200 Subject: [PATCH] feat: :boom: from now on dimnensions have to be marked as `final` --- .../framework_basics/design_overview.md | 4 ++-- .../framework_basics/text_output.md | 14 ++++++------- .../framework_basics/value_conversions.md | 6 +++--- example/currency.cpp | 2 +- .../include/mp-units/framework/dimension.h | 21 +++++++++++-------- .../mp-units/framework/dimension_concepts.h | 12 +++-------- .../mp-units/framework/quantity_spec.h | 6 +++--- .../include/mp-units/systems/angular/units.h | 2 +- .../mp-units/systems/iec80000/quantities.h | 2 +- .../mp-units/systems/isq/base_quantities.h | 14 ++++++------- test/static/concepts_test.cpp | 8 +++---- test/static/dimension_test.cpp | 10 ++++----- test/static/quantity_spec_test.cpp | 6 +++--- test/static/reference_test.cpp | 6 +++--- test/static/unit_test.cpp | 8 +++---- 15 files changed, 59 insertions(+), 62 deletions(-) diff --git a/docs/users_guide/framework_basics/design_overview.md b/docs/users_guide/framework_basics/design_overview.md index 8513ee80..3f557249 100644 --- a/docs/users_guide/framework_basics/design_overview.md +++ b/docs/users_guide/framework_basics/design_overview.md @@ -60,8 +60,8 @@ For example: the following way: ```cpp -inline constexpr struct dim_length : base_dimension<"L"> {} dim_length; -inline constexpr struct dim_time : base_dimension<"T"> {} dim_time; +inline constexpr struct dim_length final : base_dimension<"L"> {} dim_length; +inline constexpr struct dim_time final : base_dimension<"T"> {} dim_time; ``` [Derived dimensions](../../appendix/glossary.md#derived-dimension) are implicitly created diff --git a/docs/users_guide/framework_basics/text_output.md b/docs/users_guide/framework_basics/text_output.md index 6487640e..cc6c347d 100644 --- a/docs/users_guide/framework_basics/text_output.md +++ b/docs/users_guide/framework_basics/text_output.md @@ -33,13 +33,13 @@ and units of derived quantities. === "Dimensions" ```cpp - inline constexpr struct dim_length : base_dimension<"L"> {} dim_length; - inline constexpr struct dim_mass : base_dimension<"M"> {} dim_mass; - inline constexpr struct dim_time : base_dimension<"T"> {} dim_time; - inline constexpr struct dim_electric_current : base_dimension<"I"> {} dim_electric_current; - inline constexpr struct dim_thermodynamic_temperature : base_dimension<{u8"Θ", "O"}> {} dim_thermodynamic_temperature; - inline constexpr struct dim_amount_of_substance : base_dimension<"N"> {} dim_amount_of_substance; - inline constexpr struct dim_luminous_intensity : base_dimension<"J"> {} dim_luminous_intensity; + inline constexpr struct dim_length final : base_dimension<"L"> {} dim_length; + inline constexpr struct dim_mass final : base_dimension<"M"> {} dim_mass; + inline constexpr struct dim_time final : base_dimension<"T"> {} dim_time; + inline constexpr struct dim_electric_current final : base_dimension<"I"> {} dim_electric_current; + inline constexpr struct dim_thermodynamic_temperature final : base_dimension<{u8"Θ", "O"}> {} dim_thermodynamic_temperature; + inline constexpr struct dim_amount_of_substance final : base_dimension<"N"> {} dim_amount_of_substance; + inline constexpr struct dim_luminous_intensity final : base_dimension<"J"> {} dim_luminous_intensity; ``` === "Units" diff --git a/docs/users_guide/framework_basics/value_conversions.md b/docs/users_guide/framework_basics/value_conversions.md index ecc6d6c9..c1df3e6f 100644 --- a/docs/users_guide/framework_basics/value_conversions.md +++ b/docs/users_guide/framework_basics/value_conversions.md @@ -85,7 +85,7 @@ the `value_cast(q)` which always returns the most precise result: === "C++23" ```cpp - inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency; + inline constexpr struct dim_currency final : base_dimension<"$"> {} dim_currency; inline constexpr struct currency : quantity_spec {} currency; inline constexpr struct us_dollar final : named_unit<"USD", kind_of> {} us_dollar; @@ -105,7 +105,7 @@ the `value_cast(q)` which always returns the most precise result: === "C++20" ```cpp - inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency; + inline constexpr struct dim_currency final : base_dimension<"$"> {} dim_currency; inline constexpr struct currency : quantity_spec {} currency; inline constexpr struct us_dollar final : named_unit<"USD", kind_of> {} us_dollar; @@ -125,7 +125,7 @@ the `value_cast(q)` which always returns the most precise result: === "Portable" ```cpp - inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency; + inline constexpr struct dim_currency final : base_dimension<"$"> {} dim_currency; QUANTITY_SPEC(currency, dim_currency); inline constexpr struct us_dollar final : named_unit<"USD", kind_of> {} us_dollar; diff --git a/example/currency.cpp b/example/currency.cpp index bbbb55cf..b34fdc40 100644 --- a/example/currency.cpp +++ b/example/currency.cpp @@ -36,7 +36,7 @@ import mp_units.core; using namespace mp_units; // clang-format off -inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency; +inline constexpr struct dim_currency final : base_dimension<"$"> {} dim_currency; QUANTITY_SPEC(currency, dim_currency); diff --git a/src/core/include/mp-units/framework/dimension.h b/src/core/include/mp-units/framework/dimension.h index 63f409de..71d24719 100644 --- a/src/core/include/mp-units/framework/dimension.h +++ b/src/core/include/mp-units/framework/dimension.h @@ -62,9 +62,9 @@ namespace mp_units { * For example: * * @code{.cpp} - * inline constexpr struct dim_length : base_dimension<"L"> {} dim_length; - * inline constexpr struct dim_time : base_dimension<"T"> {} dim_time; - * inline constexpr struct dim_mass : base_dimension<"M"> {} dim_mass; + * inline constexpr struct dim_length final : base_dimension<"L"> {} dim_length; + * inline constexpr struct dim_time final : base_dimension<"T"> {} dim_time; + * inline constexpr struct dim_mass final : base_dimension<"M"> {} dim_mass; * @endcode * * @note A common convention in this library is to assign the same name for a type and an object of this type. @@ -87,6 +87,9 @@ struct base_dimension_less : std::bool_constant<(Lhs::symbol < Rhs::symbol)> {}; template using type_list_of_base_dimension_less = expr_less; +template +struct derived_dimension_impl : detail::expr_fractions {}; + } // namespace detail /** @@ -132,7 +135,7 @@ using type_list_of_base_dimension_less = expr_less; * instantiate this type automatically based on the dimensional arithmetic equation provided by the user. */ template -struct derived_dimension : detail::expr_fractions {}; +struct derived_dimension final : detail::derived_dimension_impl {}; /** * @brief Dimension one @@ -141,7 +144,7 @@ struct derived_dimension : detail::expr_fractions { +MP_UNITS_EXPORT inline constexpr struct dimension_one final : detail::derived_dimension_impl<> { } dimension_one; namespace detail { @@ -280,13 +283,13 @@ constexpr Out dimension_symbol_impl(Out out, const type_list& nums, con } template Out, typename... Expr> -constexpr Out dimension_symbol_impl(Out out, const derived_dimension&, const dimension_symbol_formatting& fmt, - bool negative_power) +constexpr Out dimension_symbol_impl(Out out, const derived_dimension_impl&, + const dimension_symbol_formatting& fmt, bool negative_power) { (void)negative_power; MP_UNITS_EXPECTS(negative_power == false); - return dimension_symbol_impl(out, typename derived_dimension::_num_{}, - typename derived_dimension::_den_{}, fmt); + return dimension_symbol_impl(out, typename derived_dimension_impl::_num_{}, + typename derived_dimension_impl::_den_{}, fmt); } diff --git a/src/core/include/mp-units/framework/dimension_concepts.h b/src/core/include/mp-units/framework/dimension_concepts.h index 11be622d..35913606 100644 --- a/src/core/include/mp-units/framework/dimension_concepts.h +++ b/src/core/include/mp-units/framework/dimension_concepts.h @@ -42,20 +42,13 @@ template inline constexpr bool is_derived_from_specialization_of_base_dimension = requires(T* t) { to_base_specialization_of_base_dimension(t); }; -template -inline constexpr bool is_specialization_of_base_dimension = false; - -template -inline constexpr bool is_specialization_of_base_dimension> = true; - /** * @brief A concept matching all named base dimensions in the library. * * Satisfied by all dimension types derived from a specialization of `base_dimension`. */ template -concept BaseDimension = - is_derived_from_specialization_of_base_dimension && (!is_specialization_of_base_dimension); +concept BaseDimension = is_derived_from_specialization_of_base_dimension && std::is_final_v; template struct is_dimension_one : std::false_type {}; @@ -91,7 +84,8 @@ namespace detail { * being the `dimension_one`. */ template -concept DerivedDimension = is_specialization_of || is_dimension_one::value; +concept DerivedDimension = + (is_specialization_of || is_dimension_one::value) && std::is_final_v; } // namespace detail diff --git a/src/core/include/mp-units/framework/quantity_spec.h b/src/core/include/mp-units/framework/quantity_spec.h index 383a61f3..03098bbc 100644 --- a/src/core/include/mp-units/framework/quantity_spec.h +++ b/src/core/include/mp-units/framework/quantity_spec.h @@ -199,9 +199,9 @@ MP_UNITS_EXPORT_END * For example: * * @code{.cpp} - * inline constexpr struct dim_length : base_dimension<"L"> {} dim_length; - * inline constexpr struct dim_mass : base_dimension<"M"> {} dim_mass; - * inline constexpr struct dim_time : base_dimension<"T"> {} dim_time; + * inline constexpr struct dim_length final : base_dimension<"L"> {} dim_length; + * inline constexpr struct dim_mass final : base_dimension<"M"> {} dim_mass; + * inline constexpr struct dim_time final : base_dimension<"T"> {} dim_time; * * inline constexpr struct length : quantity_spec {} length; * inline constexpr struct mass : quantity_spec {} mass; diff --git a/src/systems/include/mp-units/systems/angular/units.h b/src/systems/include/mp-units/systems/angular/units.h index e4747007..45aa42ce 100644 --- a/src/systems/include/mp-units/systems/angular/units.h +++ b/src/systems/include/mp-units/systems/angular/units.h @@ -34,7 +34,7 @@ MP_UNITS_EXPORT namespace mp_units::angular { // clang-format off -inline constexpr struct dim_angle : base_dimension<"A"> {} dim_angle; +inline constexpr struct dim_angle final : base_dimension<"A"> {} dim_angle; QUANTITY_SPEC(angle, dim_angle); QUANTITY_SPEC(solid_angle, pow<2>(angle)); diff --git a/src/systems/include/mp-units/systems/iec80000/quantities.h b/src/systems/include/mp-units/systems/iec80000/quantities.h index 04f1191f..f9b23547 100644 --- a/src/systems/include/mp-units/systems/iec80000/quantities.h +++ b/src/systems/include/mp-units/systems/iec80000/quantities.h @@ -36,7 +36,7 @@ namespace mp_units::iec80000 { // dimensions of base quantities // clang-format off -inline constexpr struct dim_traffic_intensity : base_dimension<"A"> {} dim_traffic_intensity; +inline constexpr struct dim_traffic_intensity final : base_dimension<"A"> {} dim_traffic_intensity; // clang-format on // quantities diff --git a/src/systems/include/mp-units/systems/isq/base_quantities.h b/src/systems/include/mp-units/systems/isq/base_quantities.h index 6ed87f7c..c7f4f337 100644 --- a/src/systems/include/mp-units/systems/isq/base_quantities.h +++ b/src/systems/include/mp-units/systems/isq/base_quantities.h @@ -35,13 +35,13 @@ namespace mp_units::isq { // clang-format off // dimensions of base quantities -inline constexpr struct dim_length : base_dimension<"L"> {} dim_length; -inline constexpr struct dim_mass : base_dimension<"M"> {} dim_mass; -inline constexpr struct dim_time : base_dimension<"T"> {} dim_time; -inline constexpr struct dim_electric_current : base_dimension<"I"> {} dim_electric_current; -inline constexpr struct dim_thermodynamic_temperature : base_dimension {} dim_thermodynamic_temperature; -inline constexpr struct dim_amount_of_substance : base_dimension<"N"> {} dim_amount_of_substance; -inline constexpr struct dim_luminous_intensity : base_dimension<"J"> {} dim_luminous_intensity; +inline constexpr struct dim_length final : base_dimension<"L"> {} dim_length; +inline constexpr struct dim_mass final : base_dimension<"M"> {} dim_mass; +inline constexpr struct dim_time final : base_dimension<"T"> {} dim_time; +inline constexpr struct dim_electric_current final : base_dimension<"I"> {} dim_electric_current; +inline constexpr struct dim_thermodynamic_temperature final : base_dimension {} dim_thermodynamic_temperature; +inline constexpr struct dim_amount_of_substance final : base_dimension<"N"> {} dim_amount_of_substance; +inline constexpr struct dim_luminous_intensity final : base_dimension<"J"> {} dim_luminous_intensity; // clang-format on // base quantities diff --git a/test/static/concepts_test.cpp b/test/static/concepts_test.cpp index 33fd85a5..df19711f 100644 --- a/test/static/concepts_test.cpp +++ b/test/static/concepts_test.cpp @@ -45,7 +45,7 @@ inline constexpr struct my_origin : absolute_point_origin { } my_relative_origin; -struct dim_speed : decltype(isq::dim_length / isq::dim_time) {}; +inline constexpr auto dim_speed = isq::dim_length / isq::dim_time; // BaseDimension static_assert(detail::BaseDimension); @@ -53,7 +53,7 @@ static_assert(!detail::BaseDimension) static_assert(!detail::BaseDimension); static_assert(!detail::BaseDimension(isq::dim_length))>); static_assert(!detail::BaseDimension>>); -static_assert(!detail::BaseDimension); +static_assert(!detail::BaseDimension>); static_assert(!detail::BaseDimension>); static_assert(!detail::BaseDimension); static_assert(!detail::BaseDimension); @@ -64,7 +64,7 @@ static_assert(detail::DerivedDimension); static_assert(detail::DerivedDimension(isq::dim_length))>); static_assert(detail::DerivedDimension>>); static_assert(detail::DerivedDimension); -static_assert(!detail::DerivedDimension); +static_assert(detail::DerivedDimension>); static_assert(!detail::DerivedDimension); static_assert(!detail::DerivedDimension); static_assert(!detail::DerivedDimension); @@ -76,7 +76,7 @@ static_assert(Dimension); static_assert(Dimension(isq::dim_length))>); static_assert(Dimension>>); static_assert(Dimension); -static_assert(!Dimension); +static_assert(Dimension>); static_assert(!Dimension>); static_assert(!Dimension); static_assert(!Dimension); diff --git a/test/static/dimension_test.cpp b/test/static/dimension_test.cpp index a6f0fb36..dc69eab7 100644 --- a/test/static/dimension_test.cpp +++ b/test/static/dimension_test.cpp @@ -32,12 +32,12 @@ using namespace mp_units; using dimension_one_ = struct dimension_one; // clang-format off -inline constexpr struct length_ : base_dimension<"L"> {} length; -inline constexpr struct mass_ : base_dimension<"M"> {} mass; -inline constexpr struct time_ : base_dimension<"T"> {} time; +inline constexpr struct length_ final : base_dimension<"L"> {} length; +inline constexpr struct mass_ final : base_dimension<"M"> {} mass; +inline constexpr struct time_ final : base_dimension<"T"> {} time; -inline constexpr struct my_length1_ : decltype(length) {} my_length1; -inline constexpr struct my_length2_ : decltype(length) {} my_length2; +inline constexpr auto my_length1 = length; +inline constexpr auto my_length2 = length; QUANTITY_SPEC_(q_time, time); inline constexpr struct second_ final : named_unit<"s", kind_of> {} second; diff --git a/test/static/quantity_spec_test.cpp b/test/static/quantity_spec_test.cpp index a2dbd836..7395b6a2 100644 --- a/test/static/quantity_spec_test.cpp +++ b/test/static/quantity_spec_test.cpp @@ -33,9 +33,9 @@ using dimensionless_ = struct dimensionless; using dim_one_ = struct dimension_one; // clang-format off -inline constexpr struct dim_length_ : base_dimension<"L"> {} dim_length; -inline constexpr struct dim_mass_ : base_dimension<"M"> {} dim_mass; -inline constexpr struct dim_time_ : base_dimension<"T"> {} dim_time; +inline constexpr struct dim_length_ final : base_dimension<"L"> {} dim_length; +inline constexpr struct dim_mass_ final : base_dimension<"M"> {} dim_mass; +inline constexpr struct dim_time_ final : base_dimension<"T"> {} dim_time; // quantities specification QUANTITY_SPEC_(length, dim_length); diff --git a/test/static/reference_test.cpp b/test/static/reference_test.cpp index 5c040d06..e5f6e3be 100644 --- a/test/static/reference_test.cpp +++ b/test/static/reference_test.cpp @@ -35,9 +35,9 @@ using one_ = struct one; // base dimensions // clang-format off -inline constexpr struct dim_length_ : base_dimension<"L"> {} dim_length; -inline constexpr struct dim_mass_ : base_dimension<"M"> {} dim_mass; -inline constexpr struct dim_time_ : base_dimension<"T"> {} dim_time; +inline constexpr struct dim_length_ final : base_dimension<"L"> {} dim_length; +inline constexpr struct dim_mass_ final : base_dimension<"M"> {} dim_mass; +inline constexpr struct dim_time_ final : base_dimension<"T"> {} dim_time; // quantities specification QUANTITY_SPEC_(length, dim_length); diff --git a/test/static/unit_test.cpp b/test/static/unit_test.cpp index bc39be81..60e45e48 100644 --- a/test/static/unit_test.cpp +++ b/test/static/unit_test.cpp @@ -36,10 +36,10 @@ using percent_ = struct percent; // base dimensions // clang-format off -inline constexpr struct dim_length_ : base_dimension<"L"> {} dim_length; -inline constexpr struct dim_mass_ : base_dimension<"M"> {} dim_mass; -inline constexpr struct dim_time_ : base_dimension<"T"> {} dim_time; -inline constexpr struct dim_thermodynamic_temperature_ : base_dimension {} dim_thermodynamic_temperature; +inline constexpr struct dim_length_ final : base_dimension<"L"> {} dim_length; +inline constexpr struct dim_mass_ final : base_dimension<"M"> {} dim_mass; +inline constexpr struct dim_time_ final : base_dimension<"T"> {} dim_time; +inline constexpr struct dim_thermodynamic_temperature_ final : base_dimension {} dim_thermodynamic_temperature; // quantities specification QUANTITY_SPEC_(length, dim_length);