forked from mpusz/mp-units
110 lines
4.1 KiB
ReStructuredText
110 lines
4.1 KiB
ReStructuredText
![]() |
.. namespace:: units
|
|||
|
|
|||
|
Working with Unknown Dimensions and Their Units
|
|||
|
===============================================
|
|||
|
|
|||
|
From time to time the user of this library will face an `unknown_dimension` and
|
|||
|
`unknown_coherent_unit` types. This chapters describes their purpose and usage in
|
|||
|
detail.
|
|||
|
|
|||
|
What is an unknown dimension?
|
|||
|
-----------------------------
|
|||
|
|
|||
|
As we learned in the :ref:`Dimensions` chapter, in most cases the result of multiplying
|
|||
|
or dividing two quantities of specific dimensions is a quantity of yet another dimension.
|
|||
|
|
|||
|
If such a resulting dimension is predefined by the user (and a proper header file with its
|
|||
|
definition is included in the current translation unit) :ref:`The Downcasting Facility`
|
|||
|
will determine its type. The same applies to the resulting unit. For example:
|
|||
|
|
|||
|
.. code-block::
|
|||
|
:emphasize-lines: 3,7-9
|
|||
|
|
|||
|
#include <units/physical/si/length.h>
|
|||
|
#include <units/physical/si/time.h>
|
|||
|
#include <units/physical/si/speed.h>
|
|||
|
|
|||
|
using namespace units::physical::si;
|
|||
|
|
|||
|
constexpr auto result = 144q_km / 2q_h;
|
|||
|
static_assert(std::is_same_v<decltype(result)::dimension, dim_velocity>);
|
|||
|
static_assert(std::is_same_v<decltype(result)::unit, kilometre_per_hour>);
|
|||
|
|
|||
|
However, if the resulting dimension is not predefined by the user the library framework
|
|||
|
will create an instance of an `unknown_dimension`. The coherent unit of such an unknown
|
|||
|
dimension is an `unknown_coherent_unit`. Let's see what happens with our example when
|
|||
|
we forget to include a header file with the resulting dimension definition:
|
|||
|
|
|||
|
.. code-block::
|
|||
|
:emphasize-lines: 3,9,11
|
|||
|
|
|||
|
#include <units/physical/si/length.h>
|
|||
|
#include <units/physical/si/time.h>
|
|||
|
// #include <units/physical/si/speed.h>
|
|||
|
|
|||
|
using namespace units::physical::si;
|
|||
|
|
|||
|
constexpr auto result = 144q_km / 2q_h;
|
|||
|
static_assert(std::is_same_v<decltype(result)::dimension,
|
|||
|
unknown_dimension<exp<dim_length, 1>, exp<dim_time, -1>>>);
|
|||
|
static_assert(std::is_same_v<decltype(result)::unit,
|
|||
|
scaled_unit<ratio<1, 36, 1>, unknown_coherent_unit>>);
|
|||
|
|
|||
|
|
|||
|
Operations On Unknown Dimensions And Their Units
|
|||
|
------------------------------------------------
|
|||
|
|
|||
|
For some cases we can eliminate the need to predefine a specific dimension and just use
|
|||
|
the `unknown_dimension` instead. Let's play with the previous example a bit::
|
|||
|
|
|||
|
static_assert(result.count() == 72);
|
|||
|
|
|||
|
As we can see the value stored in this quantity can be easily obtained and contains a
|
|||
|
correct result. However, if we try to print its value to the text output we will get::
|
|||
|
|
|||
|
std::cout << "Speed: " << result << '\n'; // prints 'Speed: 72 [1/36 × 10¹] m/s'
|
|||
|
|
|||
|
The output from above program should not be a surprise. It is an unknown dimensions with
|
|||
|
a scaled unknown coherent unit. The library can't know what is the symbol of such unit
|
|||
|
so it does its best and prints the unit in terms of units of base dimensions that formed
|
|||
|
this particular unknown derived dimension.
|
|||
|
|
|||
|
In case we would like to print the result in terms of base units we can simply do the
|
|||
|
following::
|
|||
|
|
|||
|
auto s = quantity_cast<unknown_coherent_unit>(result);
|
|||
|
std::cout << "Speed: " << s << '\n'; // prints 'Speed: 20 m/s'
|
|||
|
|
|||
|
.. seealso::
|
|||
|
|
|||
|
Another good example of unknown dimension usage can be found in the
|
|||
|
:ref:`box_example`::
|
|||
|
|
|||
|
std::cout << "float rise rate = " << box.fill_level(measured_mass) / fill_time << '\n';
|
|||
|
|
|||
|
|
|||
|
Temporary Results
|
|||
|
-----------------
|
|||
|
|
|||
|
In many cases there is nothing inherently wrong with having unknown dimensions and units
|
|||
|
in your program. A typical example here are temporary results of a long calculation:
|
|||
|
|
|||
|
.. code-block::
|
|||
|
:emphasize-lines: 5,7
|
|||
|
|
|||
|
auto some_long_calculation(Length auto d, Time auto t)
|
|||
|
{
|
|||
|
Speed auto s1 = avg_speed(d, t);
|
|||
|
|
|||
|
auto temp1 = s1 * 200q_km; // intermediate unknown dimension
|
|||
|
|
|||
|
Speed auto s2 = temp1 / 50q_km; // back to known dimensions again
|
|||
|
Length auto d2 = s2 * 4q_h;
|
|||
|
|
|||
|
// ...
|
|||
|
}
|
|||
|
|
|||
|
If a programmer wants to break the calculation to several lines/variables he/she does not
|
|||
|
have to ensure that the intermediate results are of predefined dimensions or just a clear
|
|||
|
science fiction :-) The final result will always be correct.
|