diff --git a/docs/blog/posts/2.1.0-released.md b/docs/blog/posts/2.1.0-released.md new file mode 100644 index 00000000..8bb0b955 --- /dev/null +++ b/docs/blog/posts/2.1.0-released.md @@ -0,0 +1,170 @@ +--- +date: 2023-12-09 +authors: + - mpusz +categories: + - Releases +--- + +# mp-units 2.1.0 released! + +**A new product version can be obtained from +[GitHub](https://github.com/mpusz/mp-units/releases/tag/v2.1.0) and +[Conan](https://conan.io/center/recipes/mp-units?version=2.1.0).** + +The list of the most significant changes introduced by the new version can be found in our +[Release Notes](../../release_notes.md#2.1.0). We will also describe the most important of them +in this post. + + + +## No more parenthesis while creating quantities with derived units + +The V2 design introduced a way to create a `quantity` by multiplying a raw value and a unit: + +```cpp +quantity q1 = 42 * m; +``` + +However, this meant that when we wanted to create a quantity having a derived unit, we had to put +parenthesis around the unit equation or create a custom value of the named unit: + +```cpp +quantity q2 = 60 * (km / h); + +constexpr auto kmph = km / h; +quantity q3 = 60 * kmph; + +quantity q4 = 50 * (1 / s); +``` + +With the new version, we removed this restriction, and now we can type: + +```cpp +quantity q5 = 60 * km / h; +quantity q6 = 50 / s; +``` + +As a side effect, we introduced a **breaking change**. We can't use the following definition of +hertz anymore: + +```cpp +inline constexpr struct hertz : named_unit<"Hz", 1 / second, kind_of> {} hertz; +``` + +and have to type either: + +```cpp +inline constexpr struct hertz : named_unit<"Hz", one / second, kind_of> {} hertz; +``` + +or + +```cpp +inline constexpr struct hertz : named_unit<"Hz", inverse(second), kind_of> {} hertz; +``` + +To be consistent, we applied the same change to the dimensions and quantity +specifications definitions. Now, to define a _frequency_ we have to type: + +=== "C++23" + + ```cpp + inline constexpr struct frequency : quantity_spec {} frequency; + ``` + +=== "C++20" + + ```cpp + inline constexpr struct frequency : quantity_spec {} frequency; + ``` + +=== "Portable" + + ```cpp + QUANTITY_SPEC(frequency, inverse(period_duration)); + ``` + +## `make_xxx` factory functions replaced with two-parameter constructors + +In the initial version of the V2 framework, if someone did not like the multiply syntax to create +a `quantity` we provided the `make_quantity()` factory function. A similar approach was used for +`quantity_point` creation. + +This version removes those (**breaking change**) and introduces two parameter constructors: + +```cpp +quantity q(42, si::metre); +quantity_point qp(q, mean_sea_level); +``` + +The above change encourages a better design and results in a terser code. + +## Improved definitions of becquerel, gray, and sievert + +In the initial V2 version, we lacked the definitions of the atomic and nuclear physics quantities, +which resulted in simplified and unsafe definitions of becquerel, gray, and sievert units. We still +do not model most of the quantities from this domain, but we've added the ones that are necessary +for the definition of those units. + +Thanks to the above, the following expressions will not compile: + +```cpp +quantity q1 = 1 * Hz + 1 * Bq; +quantity q2 = 42 * Gy; +``` + +## Compatibility with other libraries redesigned + +Another significant improvement in this version was redesigning the way we provide compatibility +with other similar libraries. The interfaces of `quantity_like_traits` and `quantity_point_like_traits` +were changed and extended to provide conversion not only from but also to entities from other +libraries (**breaking change**). + +We've also introduced an innovative approach that allows us to specify if such conversions should +happen implicitly or if they need to be forced explicitly. + +More on this subject can be found in the +[Interoperability with Other Libraries](../../users_guide/use_cases/interoperability_with_other_libraries.md) +chapter. + + +## Point origins can now be derived from each other + +Previously, each class derived from `absolute_point_origin` was considered a unique independent +point origin. On the other hand, it was OK to derive multiple classes from the same +`relative_point_origin`, and those were specifying the same point in the domain. We found this +confusing and limiting. This is why, in this version, the `absolute_point_origin` uses a CRTP idiom +to be able to detect between points that should be considered different from the ones that should +be equivalent. + +*[CRTP]: Curiously Recurring Template Pattern + +If we derive from the same instantiation of `absolute_point_origin` we end up with an equivalent +point origin. This change allows us to provide different names for the same temperature points: + +```cpp +inline constexpr struct absolute_zero : absolute_point_origin {} absolute_zero; +inline constexpr struct zeroth_kelvin : decltype(absolute_zero) {} zeroth_kelvin; + +inline constexpr struct ice_point : relative_point_origin {} ice_point; +inline constexpr struct zeroth_degree_Celsius : decltype(ice_point) {} zeroth_degree_Celsius; +``` + +Please note that this is a **breaking change** as well. + + +## Unit symbol text can now be properly used at runtime + +The interface of the previous definition of `unit_symbol` function allowed the use of the returned +buffer only at compile-time. This was too limiting as users often want to use unit symbols at +runtime (e.g., print them to the console). The new version redesigned the interface of this +function (**breaking change**) to return a buffer that can be properly used at both compilation and +runtime: + +```cpp +std::string_view unit1 = unit_symbol(m / s); +std::cout << unit1 << "\n"; // m/s +std::string_view unit2 = unit_symbol<{.solidus = unit_symbol_solidus::never}>(m / s); +std::cout << unit2 << "\n"; // m s⁻¹ +```