feat: value_cast<Unit, Representation> added

This commit is contained in:
Mateusz Pusz
2023-12-19 18:19:22 +01:00
parent 0db047803e
commit 436463b7a7
5 changed files with 121 additions and 9 deletions
+5 -5
View File
@@ -83,7 +83,7 @@ Next, let's do the same for integral and floating-point representations, but thi
using US Customary units:
```cpp title="avg_speed.cpp" linenums="54"
--8<-- "example/avg_speed.cpp:93:125"
--8<-- "example/avg_speed.cpp:93:124"
```
One important difference here is the fact that as it is not possible to make a lossless conversion
@@ -108,8 +108,8 @@ Please note how the first and third results get truncated using integral represe
In the end, we repeat the scenario for CGS units:
```cpp title="avg_speed.cpp" linenums="87"
--8<-- "example/avg_speed.cpp:127:157"
```cpp title="avg_speed.cpp" linenums="86"
--8<-- "example/avg_speed.cpp:126:155"
```
Again, we observe `value_cast` being used in the same places and consistent truncation errors
@@ -129,6 +129,6 @@ Average speed of a car that makes 2.2e+07 cm in 7200 s is 110 km/h.
The example file ends with a simple `main()` function:
```cpp title="avg_speed.cpp" linenums="118"
--8<-- "example/avg_speed.cpp:159:"
```cpp title="avg_speed.cpp" linenums="116"
--8<-- "example/avg_speed.cpp:157:"
```
@@ -77,3 +77,76 @@ quantity<si::metre, int> q3 = value_cast<int>(3.14 * m);
It is often fine to use an integral as a representation type, but in general, floating-point
types provide better precision and are privileged in the library as they are considered
to be value-preserving.
In some cases, a unit and a representation type should be changed simultaneously. Moreover,
sometimes, the order of doing those operations matters. In such cases, the library provides
the `value_cast<U, Rep>(q)` which always returns the most precise result:
=== "C++23"
```cpp
inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency;
inline constexpr struct currency : quantity_spec<dim_currency> {} currency;
inline constexpr struct us_dollar : named_unit<"USD", kind_of<currency>> {} us_dollar;
inline constexpr struct scaled_us_dollar : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar;
namespace unit_symbols {
inline constexpr auto USD = us_dollar;
inline constexpr auto USD_s = scaled_us_dollar;
} // namespace unit_symbols
using Price = quantity<currency[us_dollar], double>;
using Scaled = quantity<currency[scaled_us_dollar], std::int64_t>;
Price price = 12.95 * USD;
Scaled spx = value_cast<USD_s, std::int64_t>(price);
```
=== "C++20"
```cpp
inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency;
inline constexpr struct currency : quantity_spec<currency, dim_currency> {} currency;
inline constexpr struct us_dollar : named_unit<"USD", kind_of<currency>> {} us_dollar;
inline constexpr struct scaled_us_dollar : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar;
namespace unit_symbols {
inline constexpr auto USD = us_dollar;
inline constexpr auto USD_s = scaled_us_dollar;
} // namespace unit_symbols
using Price = quantity<currency[us_dollar], double>;
using Scaled = quantity<currency[scaled_us_dollar], std::int64_t>;
Price price = 12.95 * USD;
Scaled spx = value_cast<USD_s, std::int64_t>(price);
```
=== "Portable"
```cpp
inline constexpr struct dim_currency : base_dimension<"$"> {} dim_currency;
QUANTITY_SPEC(currency, dim_currency);
inline constexpr struct us_dollar : named_unit<"USD", kind_of<currency>> {} us_dollar;
inline constexpr struct scaled_us_dollar : named_unit<"USD_s", mag_power<10, -8> * us_dollar> {} scaled_us_dollar;
namespace unit_symbols {
inline constexpr auto USD = us_dollar;
inline constexpr auto USD_s = scaled_us_dollar;
} // namespace unit_symbols
using Price = quantity<currency[us_dollar], double>;
using Scaled = quantity<currency[scaled_us_dollar], std::int64_t>;
Price price = 12.95 * USD;
Scaled spx = value_cast<USD_s, std::int64_t>(price);
```