docs: code samples modernized

This commit is contained in:
Mateusz Pusz
2024-01-27 22:47:33 +01:00
parent 05f481d3e9
commit 99167fd3c4
7 changed files with 125 additions and 116 deletions

View File

@@ -82,7 +82,7 @@ static_assert(10 * km / (5 * km) == 2 * one);
static_assert(1000 / (1 * s) == 1 * kHz);
```
_Try it on the [Compiler Explorer](https://godbolt.org/z/81Ev7qhTd)._
_Try it on the [Compiler Explorer](https://godbolt.org/z/ox8a8dGTz)._
This library heavily uses C++20 features (concepts, classes as NTTPs, ...). Thanks to
them the user gets a powerful but still easy to use interfaces and all unit conversions
@@ -90,8 +90,10 @@ and dimensional analysis can be performed without sacrificing on runtime perform
accuracy. Please see the below example for a quick preview of basic library features:
```cpp
#include <format>
#include <iomanip>
#include <iostream>
#include <print>
import mp_units;
using namespace mp_units;
@@ -118,11 +120,11 @@ int main()
std::cout << v1 << '\n'; // 110 km/h
std::cout << std::setw(10) << std::setfill('*') << v2 << '\n'; // ***70 mi/h
std::cout << std::format("{:*^10}\n", v3); // *110 km/h*
std::cout << std::format("{:%N in %U}\n", v4); // 70 in mi/h
std::cout << std::format("{:{%N:.2f}%?%U}\n", v5); // 30.56 in m/s
std::cout << std::format("{:{%N:.2f}%?{%U:n}}\n", v6); // 31.29 in m s⁻¹
std::cout << std::format("{:%N}\n", v7); // 31
std::println("{:%N in %U}", v4); // 70 in mi/h
std::println("{:{%N:.2f}%?%U}", v5); // 30.56 m/s
std::println("{:{%N:.2f}%?{%U:n}}", v6); // 31.29 m s⁻¹
std::println("{:%N}", v7); // 31
}
```
_Try it on the [Compiler Explorer](https://godbolt.org/z/Tsesa1Pvq)._
_Try it on the [Compiler Explorer](https://godbolt.org/z/hWzxf1j1M)._

View File

@@ -69,8 +69,10 @@ performed without sacrificing accuracy. Please see the below example for a quick
=== "C++ modules"
```cpp
#include <format>
#include <iomanip>
#include <iostream>
#include <print>
import mp_units;
using namespace mp_units;
@@ -97,10 +99,10 @@ performed without sacrificing accuracy. Please see the below example for a quick
std::cout << v1 << '\n'; // 110 km/h
std::cout << std::setw(10) << std::setfill('*') << v2 << '\n'; // ***70 mi/h
std::cout << std::format("{:*^10}\n", v3); // *110 km/h*
std::cout << std::format("{:%N in %U}\n", v4); // 70 in mi/h
std::cout << std::format("{:{%N:.2f}%?%U}\n", v5); // 30.56 in m/s
std::cout << std::format("{:{%N:.2f}%?{%U:n}}\n", v6); // 31.29 in m s⁻¹
std::cout << std::format("{:%N}\n", v7); // 31
std::println("{:%N in %U}", v4); // 70 in mi/h
std::println("{:{%N:.2f}%?%U}", v5); // 30.56 m/s
std::println("{:{%N:.2f}%?{%U:n}}", v6); // 31.29 m s⁻¹
std::println("{:%N}", v7); // 31
}
```
@@ -112,8 +114,10 @@ performed without sacrificing accuracy. Please see the below example for a quick
#include <mp-units/systems/international/international.h>
#include <mp-units/systems/isq/isq.h>
#include <mp-units/systems/si/si.h>
#include <format>
#include <iomanip>
#include <iostream>
#include <print>
using namespace mp_units;
@@ -139,14 +143,14 @@ performed without sacrificing accuracy. Please see the below example for a quick
std::cout << v1 << '\n'; // 110 km/h
std::cout << std::setw(10) << std::setfill('*') << v2 << '\n'; // ***70 mi/h
std::cout << std::format("{:*^10}\n", v3); // *110 km/h*
std::cout << std::format("{:%N in %U}\n", v4); // 70 in mi/h
std::cout << std::format("{:{%N:.2f}%?%U}\n", v5); // 30.56 in m/s
std::cout << std::format("{:{%N:.2f}%?{%U:n}}\n", v6); // 31.29 in m s⁻¹
std::cout << std::format("{:%N}\n", v7); // 31
std::println("{:%N in %U}", v4); // 70 in mi/h
std::println("{:{%N:.2f}%?%U}", v5); // 30.56 m/s
std::println("{:{%N:.2f}%?{%U:n}}", v6); // 31.29 m s⁻¹
std::println("{:%N}", v7); // 31
}
```
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/Tsesa1Pvq)"
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/hWzxf1j1M)"
!!! note

View File

@@ -149,7 +149,7 @@ This introduces an additional type-safety.
=== "C++ modules"
```cpp
#include <iostream>
#include <print>
import mp_units;
int main()
@@ -157,32 +157,32 @@ This introduces an additional type-safety.
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
using namespace mp_units::usc::unit_symbols;
quantity_point temp{20. * deg_C};
std::cout << "Temperature: "
<< temp.quantity_from_zero() << " ("
<< temp.in(deg_F).quantity_from_zero() << ")\n";
std::println("Temperature: {} ({})",
temp.quantity_from_zero(),
temp.in(deg_F).quantity_from_zero());
}
```
=== "Header files"
```cpp
#include <mp-units/ostream.h>
#include <mp-units/format.h>
#include <mp-units/systems/si/si.h>
#include <mp-units/systems/usc/usc.h>
#include <iostream>
#include <print>
int main()
{
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
using namespace mp_units::usc::unit_symbols;
quantity_point temp{20. * deg_C};
std::cout << "Temperature: "
<< temp.quantity_from_zero() << " ("
<< temp.in(deg_F).quantity_from_zero() << ")\n";
std::println("Temperature: {} ({})",
temp.quantity_from_zero(),
temp.in(deg_F).quantity_from_zero());
}
```

View File

@@ -42,6 +42,7 @@ The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units)
```cpp
#include <iostream>
#include <print>
import mp_units;
using namespace mp_units;
@@ -51,36 +52,38 @@ The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units)
int main()
{
constexpr quantity dist = 364.4 * smoot;
std::cout << "Harvard Bridge length = " << dist << "(" << dist.in(usc::foot) << ", " << dist.in(si::metre) << ") ± 1 εar\n";
std::println("Harvard Bridge length = {:{%N:.5} %U} ({:{%N:.5} %U}, {:{%N:.5} %U}) ± 1 εar",
dist, dist.in(usc::foot), dist.in(si::metre));
}
```
=== "Header files"
```cpp
#include <mp-units/ostream.h>
#include <mp-units/format.h>
#include <mp-units/systems/si/si.h>
#include <mp-units/systems/usc/usc.h>
#include <iostream>
#include <print>
using namespace mp_units;
inline constexpr struct smoot : named_unit<"smoot", mag<67> * usc::inch> {} smoot;
int main()
{
constexpr quantity dist = 364.4 * smoot;
std::cout << "Harvard Bridge length = " << dist << "(" << dist.in(usc::foot) << ", " << dist.in(si::metre) << ") ± 1 εar\n";
std::println("Harvard Bridge length = {:{%N:.5} %U} ({:{%N:.5} %U}, {:{%N:.5} %U}) ± 1 εar",
dist, dist.in(usc::foot), dist.in(si::metre));
}
```
Output:
```txt
Harvard Bridge length = 364.4 smoot(2034.57 ft, 620.136 m) ± 1 εar
Harvard Bridge length = 364.4 smoot (2034.6 ft, 620.14 m) ± 1 εar
```
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/K66zKsT89)"
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/x77WEWahs)"
??? question "What is `smoot`?"

View File

@@ -61,13 +61,13 @@ constexpr auto speed_of_light_in_vacuum = 1 * si::si2019::speed_of_light_in_vacu
QuantityOf<isq::permittivity_of_vacuum> auto q = 1 / (permeability_of_vacuum * pow<2>(speed_of_light_in_vacuum));
std::cout << "permittivity of vacuum = " << q << " = " << q.in(F / m) << "\n";
std::println("permittivity of vacuum = {} = {:{%N:.3e} %U}", q, q.in(F / m));
```
The above first prints the following:
```text
permittivity of vacuum = 1 μ₀⁻¹ c⁻² = 8.85419e-12 F/m
permittivity of vacuum = 1 μ₀⁻¹ c⁻² = 8.854e-12 F/m
```
As we can clearly see, all the calculations above were just about multiplying and dividing

View File

@@ -56,15 +56,15 @@ Here is a simple example showing how to deal with such quantities:
=== "C++ modules"
```cpp
#include <iostream>
#include <print>
import mp_units;
using namespace mp_units;
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d,
quantity<si::second> t)
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> dist,
quantity<si::second> time)
{
return d / t;
return dist / time;
}
int main()
@@ -75,25 +75,24 @@ Here is a simple example showing how to deal with such quantities:
const quantity duration = 2 * h;
const quantity speed = avg_speed(distance, duration);
std::cout << "A car driving " << distance << " in " << duration
<< " has an average speed of " << speed
<< " (" << speed.in(km / h) << ")\n";
std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
distance, duration, speed, speed.in(km / h));
}
```
=== "Header files"
```cpp
#include <mp-units/ostream.h>
#include <mp-units/format.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
#include <print>
using namespace mp_units;
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d,
quantity<si::second> t)
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> dist,
quantity<si::second> time)
{
return d / t;
return dist / time;
}
int main()
@@ -104,19 +103,18 @@ Here is a simple example showing how to deal with such quantities:
const quantity duration = 2 * h;
const quantity speed = avg_speed(distance, duration);
std::cout << "A car driving " << distance << " in " << duration
<< " has an average speed of " << speed
<< " (" << speed.in(km / h) << ")\n";
std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
distance, duration, speed, speed.in(km / h));
}
```
The code above prints:
```text
A car driving 110 km in 2 h has an average speed of 15.2778 m/s (55 km/h)
A car driving 110 km in 2 h has an average speed of 15.28 m/s (55 km/h)
```
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/zWe8ecf93)"
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/svdof9dv4)"
### User-provided unit wrappers
@@ -145,10 +143,10 @@ compile-time.
For example, in case we will make the following error:
```cpp hl_lines="4"
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d,
quantity<si::second> t)
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> dist,
quantity<si::second> time)
{
return d * t; // (1)!
return dist * time; // (1)!
}
```
@@ -157,12 +155,12 @@ constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d,
the following compilation error message will be provided:
```text
In function 'constexpr mp_units::quantity<mp_units::derived_unit<mp_units::si::metre, mp_units::per<mp_units::si::second> >()> avg_speed(mp_units::quantity<mp_units::si::metre()>, mp_units::quantity<mp_units::si::second()>)':
error: could not convert 'mp_units::operator*<si::metre(), double, si::second(), double>(d, t)' from 'quantity<mp_units::derived_unit<mp_units::si::metre, mp_units::si::second>(),[...]>' to 'quantity<mp_units::derived_unit<mp_units::si::metre, mp_units::per<mp_units::si::second> >(),[...]>'
11 | return d * t;
| ~~^~~
| |
| quantity<mp_units::derived_unit<mp_units::si::metre, mp_units::si::second>(),[...]>
error: no viable conversion from returned value of type
'quantity<mp_units::derived_unit<mp_units::si::metre, mp_units::si::second>{{{}}}, [...]>'
to function return type
'quantity<mp_units::derived_unit<mp_units::si::metre, mp_units::per<mp_units::si::second>>{{{}}}, [...]>'
10 | return dist * time;
| ^~~~~~~~~~~
```
## Typed quantities
@@ -177,16 +175,16 @@ The previous example can be re-typed using typed quantities in the following way
=== "C++ modules"
```cpp
#include <iostream>
#include <print>
import mp_units;
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
constexpr quantity<isq::speed[m / s]> avg_speed(quantity<isq::length[m]> d,
quantity<isq::time[s]> t)
constexpr quantity<isq::speed[m / s]> avg_speed(quantity<isq::length[m]> dist,
quantity<isq::time[s]> time)
{
return d / t;
return dist / time;
}
int main()
@@ -195,57 +193,55 @@ The previous example can be re-typed using typed quantities in the following way
const quantity duration = isq::time(2 * h);
const quantity speed = avg_speed(distance, duration);
std::cout << "A car driving " << distance << " in " << duration
<< " has an average speed of " << speed
<< " (" << speed.in(km / h) << ")\n";
std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
distance, duration, speed, speed.in(km / h));
}
```
=== "Header files"
```cpp
#include <mp-units/ostream.h>
#include <mp-units/format.h>
#include <mp-units/systems/isq/isq.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
#include <print>
using namespace mp_units;
using namespace mp_units::si::unit_symbols;
constexpr quantity<isq::speed[m / s]> avg_speed(quantity<isq::length[m]> d,
quantity<isq::time[s]> t)
constexpr quantity<isq::speed[m / s]> avg_speed(quantity<isq::length[m]> dist,
quantity<isq::time[s]> time)
{
return d / t;
return dist / time;
}
int main()
{
const quantity distance = isq::distance(110 * km);
const quantity duration = isq::time(2 * h);
const quantity speed = avg_speed(distance, duration);
std::cout << "A car driving " << distance << " in " << duration
<< " has an average speed of " << speed
<< " (" << speed.in(km / h) << ")\n";
std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
distance, duration, speed, speed.in(km / h));
}
```
```text
A car driving 110 km in 2 h has an average speed of 15.2778 m/s (55 km/h)
A car driving 110 km in 2 h has an average speed of 15.28 m/s (55 km/h)
```
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/MWxG1j4Pc)"
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/3qdh3xhh7)"
In case we will accidentally make the same calculation error as before, this time, we will
get a bit longer error message, this time also containing information about the quantity type:
```log
In function 'constexpr mp_units::quantity<mp_units::reference<mp_units::isq::speed(), mp_units::derived_unit<mp_units::si::metre, mp_units::per<mp_units::si::second> >()>()> avg_speed(mp_units::quantity<mp_units::reference<mp_units::isq::length(), mp_units::si::metre()>()>, mp_units::quantity<mp_units::reference<mp_units::isq::time(), mp_units::si::second()>()>)':
error: could not convert 'mp_units::operator*<reference<isq::length(), si::metre()>(), double, reference<isq::time(), si::second()>(), double>(d, t)' from 'quantity<mp_units::reference<mp_units::derived_quantity_spec<mp_units::isq::length, mp_units::isq::time>(), mp_units::derived_unit<mp_units::si::metre, mp_units::si::second>()>(),[...]>' to 'quantity<mp_units::reference<mp_units::isq::speed(), mp_units::derived_unit<mp_units::si::metre, mp_units::per<mp_units::si::second> >()>(),[...]>'
12 | return d * t;
| ~~^~~
| |
| quantity<mp_units::reference<mp_units::derived_quantity_spec<mp_units::isq::length, mp_units::isq::time>(), mp_units::derived_unit<mp_units::si::metre, mp_units::si::second>()>(),[...]>
error: no viable conversion from returned value of type
'quantity<reference<get_quantity_spec(metre{}) * struct time{{{}}}, metre{} * second{{}}>{}, [...]>'
to function return type
'quantity<reference<speed{}, derived_unit<metre, per<second>>{}>{}, [...]>'
12 | return dist * time;
| ^~~~~~~~~~~
```
As we can see above, the compilation error is longer but still relatively easy to understand.
@@ -498,16 +494,21 @@ auto tank = RectangularStorageTank(horizontal_length(1'000 * mm),
This time, a compiler provides the following compilation error:
```text
In function 'int main()':
error: no matching function for call to 'RectangularStorageTank::RectangularStorageTank(mp_units::quantity<mp_units::reference<horizontal_length(), mp_units::si::milli_<mp_units::si::metre()>()>(), int>, mp_units::quantity<mp_units::reference<mp_units::isq::height(), mp_units::si::milli_<mp_units::si::metre()>()>(), int>, mp_units::quantity<mp_units::reference<mp_units::isq::width(), mp_units::si::milli_<mp_units::si::metre()>()>(), int>)'
47 | isq::width(500 * mm));
| ^
note: candidate: 'constexpr RectangularStorageTank::RectangularStorageTank(const mp_units::quantity<mp_units::reference<horizontal_length(), mp_units::si::metre()>()>&, const mp_units::quantity<mp_units::reference<mp_units::isq::width(), mp_units::si::metre()>()>&, const mp_units::quantity<mp_units::reference<mp_units::isq::height(), mp_units::si::metre()>()>&)'
35 | constexpr RectangularStorageTank(const quantity<horizontal_length[m]>& length,
| ^~~~~~~~~~~~~~~~~~~~~~
note: no known conversion for argument 2 from 'mp_units::quantity<mp_units::reference<mp_units::isq::height(), mp_units::si::milli_<mp_units::si::metre()>()>(), int>' to 'const mp_units::quantity<mp_units::reference<mp_units::isq::width(), mp_units::si::metre()>()>&'
36 | const quantity<isq::width[m]>& width,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
<source>:53:15: error: no matching constructor for initialization of 'RectangularStorageTank'
53 | auto tank = RectangularStorageTank(horizontal_length(1'000 * mm),
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
54 | isq::height(200 * mm),
| ~~~~~~~~~~~~~~~~~~~~~~
55 | isq::width(500 * mm));
| ~~~~~~~~~~~~~~~~~~~~
<source>:43:13: note: candidate constructor not viable: no known conversion from
'quantity<mp_units::reference<mp_units::isq::height{{{{{}}}}},
mp_units::si::milli_<mp_units::si::metre{{}}>{{{{}}}}>{}, int>' to
'const quantity<reference<width{}, metre{}>{}, (default) double>' for 2nd argument
43 | constexpr RectangularStorageTank(const quantity<horizontal_length[m]>& length,
| ^
44 | const quantity<isq::width[m]>& width,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
What about derived quantities? In the above example, you probably noticed that we also defined
@@ -535,16 +536,15 @@ public:
we will again get a compilation error message like this one:
```text
In constructor 'constexpr RectangularStorageTank::RectangularStorageTank(const mp_units::quantity<mp_units::reference<horizontal_length(), mp_units::si::metre()>()>&, const mp_units::quantity<mp_units::reference<mp_units::isq::width(), mp_units::si::metre()>()>&, const mp_units::quantity<mp_units::reference<mp_units::isq::height(), mp_units::si::metre()>()>&)':
error: no matching function for call to 'StorageTank::StorageTank(mp_units::quantity<mp_units::reference<mp_units::derived_quantity_spec<horizontal_length, mp_units::isq::height>(), mp_units::derived_unit<mp_units::power<mp_units::si::metre, 2> >()>(), double>, const mp_units::quantity<mp_units::reference<mp_units::isq::height(), mp_units::si::metre()>()>&)'
39 | StorageTank(length * height, height)
| ^
note: candidate: 'constexpr StorageTank::StorageTank(const mp_units::quantity<mp_units::reference<horizontal_area(), mp_units::derived_unit<mp_units::power<mp_units::si::metre, 2> >()>()>&, const mp_units::quantity<mp_units::reference<mp_units::isq::height(), mp_units::si::metre()>()>&)'
16 | constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
| ^~~~~~~~~~~
<source>:16:62: note: no known conversion for argument 1 from 'mp_units::quantity<mp_units::reference<mp_units::derived_quantity_spec<horizontal_length, mp_units::isq::height>(), mp_units::derived_unit<mp_units::power<mp_units::si::metre, 2> >()>(), double>' to 'const mp_units::quantity<mp_units::reference<horizontal_area(), mp_units::derived_unit<mp_units::power<mp_units::si::metre, 2> >()>()>&'
16 | constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
error: no matching constructor for initialization of 'StorageTank'
46 | StorageTank(length * height, height)
| ^ ~~~~~~~~~~~~~~~~~~~~~~~
<source>:22:13: note: candidate constructor not viable: no known conversion from
'quantity<mp_units::reference<mp_units::derived_quantity_spec<horizontal_length, mp_units::isq::height>{{}, {{}}},
mp_units::derived_unit<mp_units::power<mp_units::si::metre, 2>>{{{}}}>{}, [...]>' to
'const quantity<reference<horizontal_area{}, derived_unit<power<metre, 2>>{}>{}, [...]>' for 1st argument
22 | constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
!!! tip

View File

@@ -150,8 +150,8 @@ Having such a database, we can print the trip log in the following way:
```cpp
for (const auto& item : log) {
std::cout << "POI: " << item.name << "\n";
std::cout << "- Distance from home: " << item.odometer - log.front().odometer;
std::cout << "- Trip duration from start: " << (item.timestamp - log.front().timestamp).in(non_si::minute);
std::cout << "- Distance from home: " << item.odometer - log.front().odometer << "\n";
std::cout << "- Trip duration from start: " << (item.timestamp - log.front().timestamp).in(non_si::minute) << "\n";
}
```
@@ -159,7 +159,7 @@ Moreover, if Alice had reset the car's trip odometer before leaving home, we cou
one of the previous lines like that:
```cpp
std::cout << "Distance from home: " << item.odometer.quantity_from_zero();
std::cout << "Distance from home: " << item.odometer.quantity_from_zero() << "\n";
```
The above always returns a quantity measured from the "ultimate" zeroth point of a scale used for
@@ -540,8 +540,8 @@ std::println("| {:<14} | {:^18} | {:^18} | {:^18} |",
std::println("|{0:=^16}|{0:=^20}|{0:=^20}|{0:=^20}|", "");
auto print = [&](std::string_view label, auto v) {
fmt::println("| {:<14} | {:^18} | {:^18} | {:^18} |", label,
v - room_reference_temp, v - si::ice_point, v - si::absolute_zero);
std::println("| {:<14} | {:^18} | {:^18} | {:^18{%N:.2f} %U} |", label,
v - room_reference_temp, (v - si::ice_point).in(deg_C), (v - si::absolute_zero).in(deg_C));
};
print("Lowest", room_low);