docs: "C++ modules" tabs added to all the code examples

This commit is contained in:
Mateusz Pusz
2024-01-06 08:51:01 +01:00
parent 9611a64ad5
commit 39a66d2c6b
4 changed files with 566 additions and 238 deletions

View File

@@ -2,30 +2,59 @@
Here is a small example of operations possible on scalar quantities: Here is a small example of operations possible on scalar quantities:
```cpp === "C++ modules"
#include <mp-units/systems/si/si.h>
using namespace mp_units; ```cpp
using namespace mp_units::si::unit_symbols; import mp_units;
// simple numeric operations using namespace mp_units;
static_assert(10 * km / 2 == 5 * km); using namespace mp_units::si::unit_symbols;
// unit conversions // simple numeric operations
static_assert(1 * h == 3600 * s); static_assert(10 * km / 2 == 5 * km);
static_assert(1 * km + 1 * m == 1001 * m);
// derived quantities // unit conversions
static_assert(1 * km / (1 * s) == 1000 * m / s); static_assert(1 * h == 3600 * s);
static_assert(2 * km / h * (2 * h) == 4 * km); static_assert(1 * km + 1 * m == 1001 * m);
static_assert(2 * km / (2 * km / h) == 1 * h);
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)" !!! 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 *[NTTP]: Non-Type Template Parameter
```cpp === "C++ modules"
#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; ```cpp
#include <iostream>
import mp_units;
constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::length> auto d, using namespace mp_units;
QuantityOf<isq::time> auto t)
{
return d / t;
}
int main() constexpr QuantityOf<isq::speed> auto avg_speed(QuantityOf<isq::length> auto d,
{ QuantityOf<isq::time> auto t)
using namespace mp_units::si::unit_symbols; {
using namespace mp_units::international::unit_symbols; return d / t;
}
constexpr quantity v1 = 110 * km / h; int main()
constexpr quantity v2 = 70 * mph; {
constexpr quantity v3 = avg_speed(220. * isq::distance[km], 2 * h); using namespace mp_units::si::unit_symbols;
constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * h); using namespace mp_units::international::unit_symbols;
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 constexpr quantity v1 = 110 * km / h;
std::cout << v2 << '\n'; // 70 mi/h constexpr quantity v2 = 70 * mph;
std::cout << std::format("{}", v3) << '\n'; // 110 km/h constexpr quantity v3 = avg_speed(220. * isq::distance[km], 2 * h);
std::cout << std::format("{:*^14}", v4) << '\n'; // ***70 mi/h**** constexpr quantity v4 = avg_speed(isq::distance(140. * mi), 2 * h);
std::cout << std::format("{:%Q in %q}", v5) << '\n'; // 30.5556 in m/s constexpr quantity v5 = v3.in(m / s);
std::cout << std::format("{0:%Q} in {0:%q}", v6) << '\n'; // 31.2928 in m/s constexpr quantity v6 = value_cast<m / s>(v4);
std::cout << std::format("{:%Q}", v7) << '\n'; // 31 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)" !!! example "[Try it on Compiler Explorer](https://godbolt.org/z/Tsesa1Pvq)"

View File

@@ -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 Following the above, the value of a quantity in the **mp-units** library is created by multiplying
a number with a predefined unit: a number with a predefined unit:
```cpp === "C++ modules"
#include <mp-units/systems/si/si.h>
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 !!! 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 provided by this and other libraries, a quantity can also be created with a two-parameter
constructor: constructor:
```cpp === "C++ modules"
#include <mp-units/systems/si/si.h>
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 above creates an instance of `quantity<derived_unit<si::metre, per<si::second>>{}, int>`.
The same can be obtained using optional unit symbols: The same can be obtained using optional unit symbols:
```cpp === "C++ modules"
#include <mp-units/systems/si/si.h>
using namespace mp_units; ```cpp
using namespace mp_units::si::unit_symbols; 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 !!! tip
@@ -62,14 +99,27 @@ quantity q = 42 * m / s;
Quantities of the same kind can be added, subtracted, and compared to each other: Quantities of the same kind can be added, subtracted, and compared to each other:
```cpp === "C++ modules"
#include <mp-units/systems/si/si.h>
using namespace mp_units; ```cpp
using namespace mp_units::si::unit_symbols; 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: 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. The set of operations that can be done on quantity points is limited compared to quantities.
This introduces an additional type-safety. This introduces an additional type-safety.
```cpp === "C++ modules"
#include <mp-units/ostream.h>
#include <mp-units/systems/si/si.h>
#include <mp-units/systems/usc/usc.h>
#include <iostream>
int main() ```cpp
{ #include <iostream>
using namespace mp_units; import mp_units;
using namespace mp_units::si::unit_symbols;
using namespace mp_units::usc::unit_symbols;
quantity_point temp{20. * deg_C}; int main()
std::cout << "Temperature: " {
<< temp.quantity_from_zero() << " (" using namespace mp_units;
<< temp.in(deg_F).quantity_from_zero() << ")\n"; 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: The above outputs:

View File

@@ -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 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). [CMake's documentation](https://cmake.org/cmake/help/latest/manual/cmake-cxxmodules.7.html).
=== "C++ modules"
```cpp ```cpp
#include <mp-units/ostream.h> #include <iostream>
#include <mp-units/systems/si/si.h> import mp_units;
#include <mp-units/systems/usc/usc.h>
#include <iostream>
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() int main()
{ {
constexpr quantity dist = 364.4 * smoot; constexpr quantity dist = 364.4 * smoot;
std::cout << "Harvard Bridge length = " << dist << "(" << dist.in(usc::foot) << ", " << dist.in(si::metre) << ") ± 1 εar\n"; 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: Output:

View File

@@ -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: Here is a simple example showing how to deal with such quantities:
```cpp === "C++ modules"
#include <mp-units/ostream.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
using namespace mp_units; ```cpp
#include <iostream>
import mp_units;
constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d, using namespace mp_units;
quantity<si::second> t)
{
return d / t;
}
int main() constexpr quantity<si::metre / si::second> avg_speed(quantity<si::metre> d,
{ quantity<si::second> t)
using namespace mp_units::si::unit_symbols; {
return d / t;
}
const quantity distance = 110 * km; int main()
const quantity duration = 2 * h; {
const quantity speed = avg_speed(distance, duration); using namespace mp_units::si::unit_symbols;
std::cout << "A car driving " << distance << " in " << duration const quantity distance = 110 * km;
<< " has an average speed of " << speed const quantity duration = 2 * h;
<< " (" << speed.in(km / h) << ")\n"; 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: The code above prints:
@@ -144,38 +174,67 @@ accident.
The previous example can be re-typed using typed quantities in the following way: The previous example can be re-typed using typed quantities in the following way:
```cpp === "C++ modules"
#include <mp-units/ostream.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/si.h>
#include <iostream>
using namespace mp_units; ```cpp
using namespace mp_units::si::unit_symbols; #include <iostream>
import mp_units;
constexpr quantity<isq::speed[m / s]> avg_speed(quantity<isq::length[m]> d, using namespace mp_units;
quantity<isq::time[s]> t) using namespace mp_units::si::unit_symbols;
{
return d / t;
}
int main() constexpr quantity<isq::speed[m / s]> avg_speed(quantity<isq::length[m]> d,
{ quantity<isq::time[s]> t)
const quantity distance = isq::distance(110 * km); {
const quantity duration = isq::time(2 * h); return d / t;
const quantity speed = avg_speed(distance, duration); }
std::cout << "A car driving " << distance << " in " << duration int main()
<< " has an average speed of " << speed {
<< " (" << speed.in(km / h) << ")\n"; 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 ```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.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 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: 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: Let's see another example:
=== "Simple" === "C++ modules"
```cpp hl_lines="42" === "Simple"
#include <mp-units/math.h>
#include <mp-units/systems/si/si.h>
#include <numbers>
using namespace mp_units; ```cpp hl_lines="41"
#include <numbers>
import mp_units;
class StorageTank { using namespace mp_units;
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 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 { class CylindricalStorageTank : public StorageTank {
public: public:
constexpr RectangularStorageTank(const quantity<si::metre>& length, constexpr CylindricalStorageTank(const quantity<si::metre>& radius,
const quantity<si::metre>& width, const quantity<si::metre>& height) :
const quantity<si::metre>& height) : StorageTank(std::numbers::pi * pow<2>(radius), height)
StorageTank(length * width, height) {
{ }
} };
};
int main() class RectangularStorageTank : public StorageTank {
{ public:
using namespace mp_units::si::unit_symbols; constexpr RectangularStorageTank(const quantity<si::metre>& length,
auto tank = RectangularStorageTank(1'000 * mm, 500 * mm, 200 * mm); 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" === "Typed"
#include <mp-units/math.h>
#include <mp-units/systems/isq/space_and_time.h>
#include <mp-units/systems/si/si.h>
#include <numbers>
using namespace mp_units; ```cpp hl_lines="51 52 53"
using namespace mp_units::si::unit_symbols; #include <numbers>
import mp_units;
// add a custom quantity type of kind isq::length using namespace mp_units;
inline constexpr struct horizontal_length using namespace mp_units::si::unit_symbols;
: quantity_spec<isq::length> {} horizontal_length;
// add a custom derived quantity type of kind isq::area // add a custom quantity type of kind isq::length
// with a constrained quantity equation inline constexpr struct horizontal_length
inline constexpr struct horizontal_area : quantity_spec<isq::length> {} horizontal_length;
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
class StorageTank { // add a custom derived quantity type of kind isq::area
quantity<horizontal_area[m2]> base_; // with a constrained quantity equation
quantity<isq::height[m]> height_; inline constexpr struct horizontal_area
public: : quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
const quantity<isq::height[m]>& height) :
base_(base), height_(height)
{
}
// ... 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 { class CylindricalStorageTank : public StorageTank {
public: public:
constexpr RectangularStorageTank(const quantity<horizontal_length[m]>& length, constexpr CylindricalStorageTank(const quantity<isq::radius[m]>& radius,
const quantity<isq::width[m]>& width, const quantity<isq::height[m]>& height) :
const quantity<isq::height[m]>& height) : StorageTank(quantity_cast<horizontal_area>(std::numbers::pi * pow<2>(radius)),
StorageTank(length * width, height) height)
{ {
} }
}; };
int main() class RectangularStorageTank : public StorageTank {
{ public:
auto tank = RectangularStorageTank(horizontal_length(1'000 * mm), constexpr RectangularStorageTank(const quantity<horizontal_length[m]>& length,
isq::width(500 * mm), const quantity<isq::width[m]>& width,
isq::height(200 * mm)); 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 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, of simple quantities, right? Suppose someone, either by mistake or due to some refactoring,