mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-03 12:24:26 +02:00
docs: "C++ modules" tabs added to all the code examples
This commit is contained in:
@@ -2,30 +2,59 @@
|
||||
|
||||
Here is a small example of operations possible on scalar quantities:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
=== "C++ modules"
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
```cpp
|
||||
import mp_units;
|
||||
|
||||
// simple numeric operations
|
||||
static_assert(10 * km / 2 == 5 * km);
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
// unit conversions
|
||||
static_assert(1 * h == 3600 * s);
|
||||
static_assert(1 * km + 1 * m == 1001 * m);
|
||||
// simple numeric operations
|
||||
static_assert(10 * km / 2 == 5 * km);
|
||||
|
||||
// derived quantities
|
||||
static_assert(1 * km / (1 * s) == 1000 * m / s);
|
||||
static_assert(2 * km / h * (2 * h) == 4 * km);
|
||||
static_assert(2 * km / (2 * km / h) == 1 * h);
|
||||
// unit conversions
|
||||
static_assert(1 * h == 3600 * s);
|
||||
static_assert(1 * km + 1 * m == 1001 * m);
|
||||
|
||||
static_assert(2 * m * (3 * m) == 6 * m2);
|
||||
// derived quantities
|
||||
static_assert(1 * km / (1 * s) == 1000 * m / s);
|
||||
static_assert(2 * km / h * (2 * h) == 4 * km);
|
||||
static_assert(2 * km / (2 * km / h) == 1 * h);
|
||||
|
||||
static_assert(10 * km / (5 * km) == 2 * one);
|
||||
static_assert(2 * m * (3 * m) == 6 * m2);
|
||||
|
||||
static_assert(1000 / (1 * s) == 1 * kHz);
|
||||
```
|
||||
static_assert(10 * km / (5 * km) == 2 * one);
|
||||
|
||||
static_assert(1000 / (1 * s) == 1 * kHz);
|
||||
```
|
||||
|
||||
=== "Header files"
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
// simple numeric operations
|
||||
static_assert(10 * km / 2 == 5 * km);
|
||||
|
||||
// unit conversions
|
||||
static_assert(1 * h == 3600 * s);
|
||||
static_assert(1 * km + 1 * m == 1001 * m);
|
||||
|
||||
// derived quantities
|
||||
static_assert(1 * km / (1 * s) == 1000 * m / s);
|
||||
static_assert(2 * km / h * (2 * h) == 4 * km);
|
||||
static_assert(2 * km / (2 * km / h) == 1 * h);
|
||||
|
||||
static_assert(2 * m * (3 * m) == 6 * m2);
|
||||
|
||||
static_assert(10 * km / (5 * km) == 2 * one);
|
||||
|
||||
static_assert(1000 / (1 * s) == 1 * kHz);
|
||||
```
|
||||
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/81Ev7qhTd)"
|
||||
|
||||
@@ -37,44 +66,83 @@ performed without sacrificing accuracy. Please see the below example for a quick
|
||||
|
||||
*[NTTP]: Non-Type Template Parameter
|
||||
|
||||
```cpp
|
||||
#include <mp-units/format.h>
|
||||
#include <mp-units/ostream.h>
|
||||
#include <mp-units/systems/international/international.h>
|
||||
#include <mp-units/systems/isq/isq.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <iostream>
|
||||
=== "C++ modules"
|
||||
|
||||
using namespace mp_units;
|
||||
```cpp
|
||||
#include <iostream>
|
||||
import mp_units;
|
||||
|
||||
constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::length> auto d,
|
||||
QuantityOf<isq::time> auto t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
using namespace mp_units;
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
using namespace mp_units::international::unit_symbols;
|
||||
constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::length> auto d,
|
||||
QuantityOf<isq::time> auto t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
constexpr quantity v1 = 110 * km / h;
|
||||
constexpr quantity v2 = 70 * mph;
|
||||
constexpr quantity v3 = avg_speed(220. * isq::distance[km], 2 * h);
|
||||
constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * h);
|
||||
constexpr quantity v5 = v3.in(m / s);
|
||||
constexpr quantity v6 = value_cast<m / s>(v4);
|
||||
constexpr quantity v7 = value_cast<int>(v6);
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
using namespace mp_units::international::unit_symbols;
|
||||
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << v2 << '\n'; // 70 mi/h
|
||||
std::cout << std::format("{}", v3) << '\n'; // 110 km/h
|
||||
std::cout << std::format("{:*^14}", v4) << '\n'; // ***70 mi/h****
|
||||
std::cout << std::format("{:%Q in %q}", v5) << '\n'; // 30.5556 in m/s
|
||||
std::cout << std::format("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s
|
||||
std::cout << std::format("{:%Q}", v7) << '\n'; // 31
|
||||
}
|
||||
```
|
||||
constexpr quantity v1 = 110 * km / h;
|
||||
constexpr quantity v2 = 70 * mph;
|
||||
constexpr quantity v3 = avg_speed(220. * isq::distance[km], 2 * h);
|
||||
constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * h);
|
||||
constexpr quantity v5 = v3.in(m / s);
|
||||
constexpr quantity v6 = value_cast<m / s>(v4);
|
||||
constexpr quantity v7 = value_cast<int>(v6);
|
||||
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << v2 << '\n'; // 70 mi/h
|
||||
std::cout << std::format("{}", v3) << '\n'; // 110 km/h
|
||||
std::cout << std::format("{:*^14}", v4) << '\n'; // ***70 mi/h****
|
||||
std::cout << std::format("{:%Q in %q}", v5) << '\n'; // 30.5556 in m/s
|
||||
std::cout << std::format("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s
|
||||
std::cout << std::format("{:%Q}", v7) << '\n'; // 31
|
||||
}
|
||||
```
|
||||
|
||||
=== "Header files"
|
||||
|
||||
```cpp
|
||||
#include <mp-units/format.h>
|
||||
#include <mp-units/ostream.h>
|
||||
#include <mp-units/systems/international/international.h>
|
||||
#include <mp-units/systems/isq/isq.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::length> auto d,
|
||||
QuantityOf<isq::time> auto t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
using namespace mp_units::international::unit_symbols;
|
||||
|
||||
constexpr quantity v1 = 110 * km / h;
|
||||
constexpr quantity v2 = 70 * mph;
|
||||
constexpr quantity v3 = avg_speed(220. * isq::distance[km], 2 * h);
|
||||
constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * h);
|
||||
constexpr quantity v5 = v3.in(m / s);
|
||||
constexpr quantity v6 = value_cast<m / s>(v4);
|
||||
constexpr quantity v7 = value_cast<int>(v6);
|
||||
|
||||
std::cout << v1 << '\n'; // 110 km/h
|
||||
std::cout << v2 << '\n'; // 70 mi/h
|
||||
std::cout << std::format("{}", v3) << '\n'; // 110 km/h
|
||||
std::cout << std::format("{:*^14}", v4) << '\n'; // ***70 mi/h****
|
||||
std::cout << std::format("{:%Q in %q}", v5) << '\n'; // 30.5556 in m/s
|
||||
std::cout << std::format("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s
|
||||
std::cout << std::format("{:%Q}", v7) << '\n'; // 31
|
||||
}
|
||||
```
|
||||
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/Tsesa1Pvq)"
|
||||
|
||||
|
@@ -20,13 +20,25 @@ The [SI Brochure](../appendix/references.md#SIBrochure) says:
|
||||
Following the above, the value of a quantity in the **mp-units** library is created by multiplying
|
||||
a number with a predefined unit:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
=== "C++ modules"
|
||||
|
||||
using namespace mp_units;
|
||||
```cpp
|
||||
import mp_units;
|
||||
|
||||
quantity q = 42 * si::metre / si::second;
|
||||
```
|
||||
using namespace mp_units;
|
||||
|
||||
quantity q = 42 * si::metre / si::second;
|
||||
```
|
||||
|
||||
=== "Header files"
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
quantity q = 42 * si::metre / si::second;
|
||||
```
|
||||
|
||||
!!! info
|
||||
|
||||
@@ -34,25 +46,50 @@ quantity q = 42 * si::metre / si::second;
|
||||
provided by this and other libraries, a quantity can also be created with a two-parameter
|
||||
constructor:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
=== "C++ modules"
|
||||
|
||||
using namespace mp_units;
|
||||
```cpp
|
||||
import mp_units;
|
||||
|
||||
quantity q{42, si::metre / si::second};
|
||||
```
|
||||
using namespace mp_units;
|
||||
|
||||
quantity q{42, si::metre / si::second};
|
||||
```
|
||||
|
||||
=== "Header files"
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
quantity q{42, si::metre / si::second};
|
||||
```
|
||||
|
||||
The above creates an instance of `quantity<derived_unit<si::metre, per<si::second>>{}, int>`.
|
||||
The same can be obtained using optional unit symbols:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
=== "C++ modules"
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
```cpp
|
||||
import mp_units;
|
||||
|
||||
quantity q = 42 * m / s;
|
||||
```
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
quantity q = 42 * m / s;
|
||||
```
|
||||
|
||||
=== "Header files"
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
quantity q = 42 * m / s;
|
||||
```
|
||||
|
||||
!!! tip
|
||||
|
||||
@@ -62,14 +99,27 @@ quantity q = 42 * m / s;
|
||||
|
||||
Quantities of the same kind can be added, subtracted, and compared to each other:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
=== "C++ modules"
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
```cpp
|
||||
import mp_units;
|
||||
|
||||
static_assert(1 * km + 50 * m == 1050 * m);
|
||||
```
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
static_assert(1 * km + 50 * m == 1050 * m);
|
||||
```
|
||||
|
||||
=== "Header files"
|
||||
|
||||
```cpp
|
||||
#include <mp-units/systems/si/si.h>
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
static_assert(1 * km + 50 * m == 1050 * m);
|
||||
```
|
||||
|
||||
Various quantities can be multiplied or divided by each other:
|
||||
|
||||
@@ -96,24 +146,45 @@ Quantity points should be used in all places where adding two values is meaningl
|
||||
The set of operations that can be done on quantity points is limited compared to quantities.
|
||||
This introduces an additional type-safety.
|
||||
|
||||
```cpp
|
||||
#include <mp-units/ostream.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <mp-units/systems/usc/usc.h>
|
||||
#include <iostream>
|
||||
=== "C++ modules"
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
using namespace mp_units::usc::unit_symbols;
|
||||
```cpp
|
||||
#include <iostream>
|
||||
import mp_units;
|
||||
|
||||
quantity_point temp{20. * deg_C};
|
||||
std::cout << "Temperature: "
|
||||
<< temp.quantity_from_zero() << " ("
|
||||
<< temp.in(deg_F).quantity_from_zero() << ")\n";
|
||||
}
|
||||
```
|
||||
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";
|
||||
}
|
||||
```
|
||||
|
||||
=== "Header files"
|
||||
|
||||
```cpp
|
||||
#include <mp-units/ostream.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <mp-units/systems/usc/usc.h>
|
||||
#include <iostream>
|
||||
|
||||
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";
|
||||
}
|
||||
```
|
||||
|
||||
The above outputs:
|
||||
|
||||
|
@@ -38,23 +38,41 @@ The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units)
|
||||
More requirements for C++ modules support can be found in the
|
||||
[CMake's documentation](https://cmake.org/cmake/help/latest/manual/cmake-cxxmodules.7.html).
|
||||
|
||||
=== "C++ modules"
|
||||
|
||||
```cpp
|
||||
#include <mp-units/ostream.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <mp-units/systems/usc/usc.h>
|
||||
#include <iostream>
|
||||
```cpp
|
||||
#include <iostream>
|
||||
import mp_units;
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units;
|
||||
|
||||
inline constexpr struct smoot : named_unit<"smoot", mag<67> * usc::inch> {} smoot;
|
||||
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";
|
||||
}
|
||||
```
|
||||
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";
|
||||
}
|
||||
```
|
||||
|
||||
=== "Header files"
|
||||
|
||||
```cpp
|
||||
#include <mp-units/ostream.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <mp-units/systems/usc/usc.h>
|
||||
#include <iostream>
|
||||
|
||||
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";
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
|
@@ -53,32 +53,62 @@ have shorter type identifiers, resulting in easier-to-understand error messages
|
||||
|
||||
Here is a simple example showing how to deal with such quantities:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/ostream.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <iostream>
|
||||
=== "C++ modules"
|
||||
|
||||
using namespace mp_units;
|
||||
```cpp
|
||||
#include <iostream>
|
||||
import mp_units;
|
||||
|
||||
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d,
|
||||
quantity<si::second> t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
using namespace mp_units;
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d,
|
||||
quantity<si::second> t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
const quantity distance = 110 * km;
|
||||
const quantity duration = 2 * h;
|
||||
const quantity speed = avg_speed(distance, duration);
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
std::cout << "A car driving " << distance << " in " << duration
|
||||
<< " has an average speed of " << speed
|
||||
<< " (" << speed.in(km / h) << ")\n";
|
||||
}
|
||||
```
|
||||
const quantity distance = 110 * km;
|
||||
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";
|
||||
}
|
||||
```
|
||||
|
||||
=== "Header files"
|
||||
|
||||
```cpp
|
||||
#include <mp-units/ostream.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d,
|
||||
quantity<si::second> t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
const quantity distance = 110 * km;
|
||||
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";
|
||||
}
|
||||
```
|
||||
|
||||
The code above prints:
|
||||
|
||||
@@ -144,38 +174,67 @@ accident.
|
||||
|
||||
The previous example can be re-typed using typed quantities in the following way:
|
||||
|
||||
```cpp
|
||||
#include <mp-units/ostream.h>
|
||||
#include <mp-units/systems/isq/space_and_time.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <iostream>
|
||||
=== "C++ modules"
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
```cpp
|
||||
#include <iostream>
|
||||
import mp_units;
|
||||
|
||||
constexpr quantity<isq::speed[m / s]> avg_speed(quantity<isq::length[m]> d,
|
||||
quantity<isq::time[s]> t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
int main()
|
||||
{
|
||||
const quantity distance = isq::distance(110 * km);
|
||||
const quantity duration = isq::time(2 * h);
|
||||
const quantity speed = avg_speed(distance, duration);
|
||||
constexpr quantity<isq::speed[m / s]> avg_speed(quantity<isq::length[m]> d,
|
||||
quantity<isq::time[s]> t)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
std::cout << "A car driving " << distance << " in " << duration
|
||||
<< " has an average speed of " << speed
|
||||
<< " (" << speed.in(km / h) << ")\n";
|
||||
}
|
||||
```
|
||||
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";
|
||||
}
|
||||
```
|
||||
|
||||
=== "Header files"
|
||||
|
||||
```cpp
|
||||
#include <mp-units/ostream.h>
|
||||
#include <mp-units/systems/isq/isq.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <iostream>
|
||||
|
||||
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)
|
||||
{
|
||||
return d / t;
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
```
|
||||
|
||||
```text
|
||||
A car driving 110 km in 2 h has an average speed of 15.2778 m/s (55 km/h)
|
||||
```
|
||||
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/q3PzMzqsh)"
|
||||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/MWxG1j4Pc)"
|
||||
|
||||
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:
|
||||
@@ -200,116 +259,228 @@ but there are scenarios where they offer additional level of safety.
|
||||
|
||||
Let's see another example:
|
||||
|
||||
=== "Simple"
|
||||
=== "C++ modules"
|
||||
|
||||
```cpp hl_lines="42"
|
||||
#include <mp-units/math.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <numbers>
|
||||
=== "Simple"
|
||||
|
||||
using namespace mp_units;
|
||||
```cpp hl_lines="41"
|
||||
#include <numbers>
|
||||
import mp_units;
|
||||
|
||||
class StorageTank {
|
||||
quantity<square(si::metre)> base_;
|
||||
quantity<si::metre> height_;
|
||||
public:
|
||||
constexpr StorageTank(const quantity<square(si::metre)>& base,
|
||||
const quantity<si::metre>& height) :
|
||||
base_(base), height_(height)
|
||||
{
|
||||
}
|
||||
using namespace mp_units;
|
||||
|
||||
// ...
|
||||
};
|
||||
class StorageTank {
|
||||
quantity<square(si::metre)> base_;
|
||||
quantity<si::metre> height_;
|
||||
public:
|
||||
constexpr StorageTank(const quantity<square(si::metre)>& base,
|
||||
const quantity<si::metre>& height) :
|
||||
base_(base), height_(height)
|
||||
{
|
||||
}
|
||||
|
||||
class CylindricalStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr CylindricalStorageTank(const quantity<si::metre>& radius,
|
||||
const quantity<si::metre>& height) :
|
||||
StorageTank(std::numbers::pi * pow<2>(radius), height)
|
||||
{
|
||||
}
|
||||
};
|
||||
// ...
|
||||
};
|
||||
|
||||
class RectangularStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr RectangularStorageTank(const quantity<si::metre>& length,
|
||||
const quantity<si::metre>& width,
|
||||
const quantity<si::metre>& height) :
|
||||
StorageTank(length * width, height)
|
||||
{
|
||||
}
|
||||
};
|
||||
class CylindricalStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr CylindricalStorageTank(const quantity<si::metre>& radius,
|
||||
const quantity<si::metre>& height) :
|
||||
StorageTank(std::numbers::pi * pow<2>(radius), height)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
auto tank = RectangularStorageTank(1'000 * mm, 500 * mm, 200 * mm);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
class RectangularStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr RectangularStorageTank(const quantity<si::metre>& length,
|
||||
const quantity<si::metre>& width,
|
||||
const quantity<si::metre>& height) :
|
||||
StorageTank(length * width, height)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
=== "Typed"
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
auto tank = RectangularStorageTank(1'000 * mm, 500 * mm, 200 * mm);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
```cpp hl_lines="53 54 55"
|
||||
#include <mp-units/math.h>
|
||||
#include <mp-units/systems/isq/space_and_time.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <numbers>
|
||||
=== "Typed"
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
```cpp hl_lines="51 52 53"
|
||||
#include <numbers>
|
||||
import mp_units;
|
||||
|
||||
// add a custom quantity type of kind isq::length
|
||||
inline constexpr struct horizontal_length
|
||||
: quantity_spec<isq::length> {} horizontal_length;
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
// add a custom derived quantity type of kind isq::area
|
||||
// with a constrained quantity equation
|
||||
inline constexpr struct horizontal_area
|
||||
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
||||
// add a custom quantity type of kind isq::length
|
||||
inline constexpr struct horizontal_length
|
||||
: quantity_spec<isq::length> {} horizontal_length;
|
||||
|
||||
class StorageTank {
|
||||
quantity<horizontal_area[m2]> base_;
|
||||
quantity<isq::height[m]> height_;
|
||||
public:
|
||||
constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
base_(base), height_(height)
|
||||
{
|
||||
}
|
||||
// add a custom derived quantity type of kind isq::area
|
||||
// with a constrained quantity equation
|
||||
inline constexpr struct horizontal_area
|
||||
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
||||
|
||||
// ...
|
||||
};
|
||||
class StorageTank {
|
||||
quantity<horizontal_area[m2]> base_;
|
||||
quantity<isq::height[m]> height_;
|
||||
public:
|
||||
constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
base_(base), height_(height)
|
||||
{
|
||||
}
|
||||
|
||||
class CylindricalStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr CylindricalStorageTank(const quantity<isq::radius[m]>& radius,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
StorageTank(quantity_cast<horizontal_area>(std::numbers::pi * pow<2>(radius)),
|
||||
height)
|
||||
{
|
||||
}
|
||||
};
|
||||
// ...
|
||||
};
|
||||
|
||||
class RectangularStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr RectangularStorageTank(const quantity<horizontal_length[m]>& length,
|
||||
const quantity<isq::width[m]>& width,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
StorageTank(length * width, height)
|
||||
{
|
||||
}
|
||||
};
|
||||
class CylindricalStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr CylindricalStorageTank(const quantity<isq::radius[m]>& radius,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
StorageTank(quantity_cast<horizontal_area>(std::numbers::pi * pow<2>(radius)),
|
||||
height)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
auto tank = RectangularStorageTank(horizontal_length(1'000 * mm),
|
||||
isq::width(500 * mm),
|
||||
isq::height(200 * mm));
|
||||
// ...
|
||||
}
|
||||
```
|
||||
class RectangularStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr RectangularStorageTank(const quantity<horizontal_length[m]>& length,
|
||||
const quantity<isq::width[m]>& width,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
StorageTank(length * width, height)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
auto tank = RectangularStorageTank(horizontal_length(1'000 * mm),
|
||||
isq::width(500 * mm),
|
||||
isq::height(200 * mm));
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
=== "Header files"
|
||||
|
||||
=== "Simple"
|
||||
|
||||
```cpp hl_lines="42"
|
||||
#include <mp-units/math.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <numbers>
|
||||
|
||||
using namespace mp_units;
|
||||
|
||||
class StorageTank {
|
||||
quantity<square(si::metre)> base_;
|
||||
quantity<si::metre> height_;
|
||||
public:
|
||||
constexpr StorageTank(const quantity<square(si::metre)>& base,
|
||||
const quantity<si::metre>& height) :
|
||||
base_(base), height_(height)
|
||||
{
|
||||
}
|
||||
|
||||
// ...
|
||||
};
|
||||
|
||||
class CylindricalStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr CylindricalStorageTank(const quantity<si::metre>& radius,
|
||||
const quantity<si::metre>& height) :
|
||||
StorageTank(std::numbers::pi * pow<2>(radius), height)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class RectangularStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr RectangularStorageTank(const quantity<si::metre>& length,
|
||||
const quantity<si::metre>& width,
|
||||
const quantity<si::metre>& height) :
|
||||
StorageTank(length * width, height)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
auto tank = RectangularStorageTank(1'000 * mm, 500 * mm, 200 * mm);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
=== "Typed"
|
||||
|
||||
```cpp hl_lines="53 54 55"
|
||||
#include <mp-units/math.h>
|
||||
#include <mp-units/systems/isq/isq.h>
|
||||
#include <mp-units/systems/si/si.h>
|
||||
#include <numbers>
|
||||
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
// add a custom quantity type of kind isq::length
|
||||
inline constexpr struct horizontal_length
|
||||
: quantity_spec<isq::length> {} horizontal_length;
|
||||
|
||||
// add a custom derived quantity type of kind isq::area
|
||||
// with a constrained quantity equation
|
||||
inline constexpr struct horizontal_area
|
||||
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
||||
|
||||
class StorageTank {
|
||||
quantity<horizontal_area[m2]> base_;
|
||||
quantity<isq::height[m]> height_;
|
||||
public:
|
||||
constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
base_(base), height_(height)
|
||||
{
|
||||
}
|
||||
|
||||
// ...
|
||||
};
|
||||
|
||||
class CylindricalStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr CylindricalStorageTank(const quantity<isq::radius[m]>& radius,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
StorageTank(quantity_cast<horizontal_area>(std::numbers::pi * pow<2>(radius)),
|
||||
height)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class RectangularStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr RectangularStorageTank(const quantity<horizontal_length[m]>& length,
|
||||
const quantity<isq::width[m]>& width,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
StorageTank(length * width, height)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
auto tank = RectangularStorageTank(horizontal_length(1'000 * mm),
|
||||
isq::width(500 * mm),
|
||||
isq::height(200 * mm));
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
In the above example, the highlighted call doesn't look that safe anymore in the case
|
||||
of simple quantities, right? Suppose someone, either by mistake or due to some refactoring,
|
||||
|
Reference in New Issue
Block a user