Files
mp-units/docs/blog/posts/2.3.0-released.md
T

3.7 KiB

draft, date, authors, categories
draft date authors categories
true 2024-06-15
mpusz
Releases

mp-units 2.3.0 released!

A new product version can be obtained from GitHub and Conan.

This release fine-tunes many key features of the library. This post describes those and a few other smaller interesting improvements, while a much longer list of the most significant changes introduced by the new version can be found in our Release Notes.

Quantity reference specifiers

The features described in this chapter directly solve an issue raised on std-proposals reflector. As it was reported, the code below may look correct, but it provides an invalid result:

quantity Volume = 1.0 * m3;
quantity Temperature = 28.0 * deg_C;
quantity n_ = 0.04401 * kg / mol;
quantity R_boltzman = 8.314 * N * m / (K * mol);
quantity mass = 40.0 * kg;
quantity Pressure = R_boltzman * Temperature.in(K) * mass / n_ / Volume;
std::cout << Pressure << "\n";

The problem is related to the accidental usage of a quantity rather than quantity_point for Temperature. This means that after conversion to kelvins, we will get 28 K instead of the expected 301.15 K, which will corrupt all further calculations.

A correct code should use a quantity_point:

quantity_point Temperature(28.0 * deg_C);

This might be an obvious thing for domain experts, but new users of the library may not be aware of the affine space abstractions and how they influence temperature handling.

After a lengthy discussion on handling such scenarios, we decided to aid the quantity and quantity_point construction with absolute<Reference> and delta<Reference> quantity reference specifiers. This applies to:

  • the multiply syntax,
  • 2-parameter quantity constructor.

Here are the main points of this new design:

  1. All references/units that do not specify point origin (are not offset units) in their definition are considered delta by default. This means that 42 * m creates a quantity and is the same as calling 42 * delta<m>.
  2. Multiply syntax is extended to allow quantity_point creation with the 42 * absolute<m> syntax. This will provide an implicit zeroth point origin.
  3. For units that specify a point origin (si::kelvin, si::degree_Celsius, and    usc::degree_Fahrenheit), the user always needs to specify a modifier. This means that:     - 4 * deg_C does not compile,     - 4 * delta<deg_C> creates a quantity.     - 4 * absolute<deg_C> creates a quantity_point.
  4. The 2-parameter quantity constructor requires the same:
quantity q1(4, m); // OK
quantity q2(4, delta<m>); // OK
quantity q3(4, absolute<m>); // Compile-time error
quantity q4(4, deg_C); // Compile-time error
quantity q5(4, delta<deg_C>); // OK
quantity q6(4, absolute<deg_C>); // Compile-time error

The delta and absolute modifiers are stripped upon construction, so the resulting quantity and quantity_point types use the underlying unit in its type.

With such changes, the offending code will not compile, forcing the user to think more about what is written. To enable the compilation, the user has to type one of the following:

  • quantity_point Temperature(28.0 * delta<deg_C>);
  • quantity_point Temperature = 28.0 * absolute<deg_C>;

If the user still insists on using quantity instead of a quantity_point, the code will have to be written in the following way to compile successfully:

quantity Temperature = 28.0 * delta<deg_C>;

This will yield an invalid result, but now, hopefully, it is clearly readable in the code what is wrong here.