mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-01 03:14:29 +02:00
docs: improved the docs for using-directives of unit_symbols
This commit is contained in:
@@ -95,39 +95,86 @@ The same can be obtained using optional unit symbols:
|
||||
|
||||
Unit symbols introduce a lot of short identifiers into the current scope, which may cause
|
||||
naming collisions with unrelated but already existing identifiers in the code base.
|
||||
This is why unit symbols are opt-in.
|
||||
This is why unit symbols are opt-in and typically should be imported only in the context
|
||||
where they are being used (e.g., function scope).
|
||||
|
||||
A user has several options here to choose from depending on the required scenario and possible
|
||||
naming conflicts:
|
||||
|
||||
- explicitly "import" all of them from a dedicated `unit_symbols` namespace with a
|
||||
[using-directive](https://en.cppreference.com/w/cpp/language/namespace#Using-directives):
|
||||
=== "using-directive"
|
||||
|
||||
Explicitly "import" all of the symbols of a specific system of units from a dedicated
|
||||
`unit_symbols` namespace with a
|
||||
[using-directive](https://en.cppreference.com/w/cpp/language/namespace#Using-directives):
|
||||
|
||||
```cpp
|
||||
using namespace mp_units;
|
||||
using namespace mp_units::si::unit_symbols; // imports all the SI symbols at once
|
||||
|
||||
quantity q = 42 * m / s;
|
||||
void foo(double speed_m_s)
|
||||
{
|
||||
// imports all the SI symbols at once
|
||||
using namespace si::unit_symbols;
|
||||
quantity speed = speed_m_s * m / s;
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
- selectively select only the required and not-conflicting ones with
|
||||
[using-declarations](https://en.cppreference.com/w/cpp/language/using_declaration):
|
||||
!!! note
|
||||
|
||||
This solution is perfect for small and isolated scopes but can cause surprising issues
|
||||
when used in larger scopes or when used for the entire program namespace.
|
||||
|
||||
There are 29 named units in SI, and each of them has many prefixed variations (e.g.,
|
||||
`ng`, `kcd`, ...). It is pretty easy to introduce a name collision with those.
|
||||
|
||||
=== "using-declaration"
|
||||
|
||||
Selectively bring only the required and not-conflicting symbols with
|
||||
[using-declarations](https://en.cppreference.com/w/cpp/language/using_declaration):
|
||||
|
||||
```cpp
|
||||
using namespace mp_units;
|
||||
using si::unit_symbols::m;
|
||||
using si::unit_symbols::s;
|
||||
|
||||
quantity q = 42 * m / s;
|
||||
void foo(double N)
|
||||
{
|
||||
// 'N' function parameter would collide with the SI symbol for Newton, so we only bring what we need
|
||||
using si::unit_symbols::m;
|
||||
using si::unit_symbols::s;
|
||||
quantity speed = N * m / s;
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
- specify a custom not conflicting unit identifier for a unit:
|
||||
=== "custom short identifier"
|
||||
|
||||
Specify a custom not conflicting unit identifier for a unit:
|
||||
|
||||
```cpp
|
||||
using namespace mp_units;
|
||||
constexpr Unit auto mps = si::metre / si::second;
|
||||
|
||||
quantity q = 42 * mps;
|
||||
void foo(double speed_m_s)
|
||||
{
|
||||
// names of some local variables are conflicting with the symbols we want to use
|
||||
auto m = ...;
|
||||
auto s = ...;
|
||||
|
||||
constexpr Unit auto mps = si::metre / si::second;
|
||||
quantity speed = speed_m_s * mps;
|
||||
}
|
||||
```
|
||||
|
||||
=== "unit names"
|
||||
|
||||
Full unit names are straightforward to use and often provide the most readable code:
|
||||
|
||||
```cpp
|
||||
using namespace mp_units;
|
||||
|
||||
void foo(double m, double s)
|
||||
{
|
||||
quantity speed = m * si::metre / (s * si::second);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Quantities of the same kind can be added, subtracted, and compared to each other:
|
||||
|
@@ -179,16 +179,17 @@ The previous example can be re-typed using typed quantities in the following way
|
||||
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]> dist,
|
||||
quantity<isq::time[s]> time)
|
||||
constexpr quantity<isq::speed[si::metre / si::second]> avg_speed(quantity<isq::length[si::metre]> dist,
|
||||
quantity<isq::time[si::second]> time)
|
||||
{
|
||||
return dist / time;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
const quantity distance = isq::distance(110 * km);
|
||||
const quantity duration = isq::time(2 * h);
|
||||
const quantity speed = avg_speed(distance, duration);
|
||||
@@ -207,16 +208,17 @@ The previous example can be re-typed using typed quantities in the following way
|
||||
#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]> dist,
|
||||
quantity<isq::time[s]> time)
|
||||
constexpr quantity<isq::speed[si::metre / si::second]> avg_speed(quantity<isq::length[si::metre]> dist,
|
||||
quantity<isq::time[si::second]> time)
|
||||
{
|
||||
return dist / time;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
|
||||
const quantity distance = isq::distance(110 * km);
|
||||
const quantity duration = isq::time(2 * h);
|
||||
const quantity speed = avg_speed(distance, duration);
|
||||
@@ -312,7 +314,6 @@ Let's see another example:
|
||||
import mp_units;
|
||||
|
||||
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
|
||||
@@ -324,11 +325,11 @@ Let's see another example:
|
||||
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
||||
|
||||
class StorageTank {
|
||||
quantity<horizontal_area[m2]> base_;
|
||||
quantity<isq::height[m]> height_;
|
||||
quantity<horizontal_area[square(si::metre)]> base_;
|
||||
quantity<isq::height[si::metre]> height_;
|
||||
public:
|
||||
constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
constexpr StorageTank(const quantity<horizontal_area[square(si::metre)]>& base,
|
||||
const quantity<isq::height[si::metre]>& height) :
|
||||
base_(base), height_(height)
|
||||
{
|
||||
}
|
||||
@@ -338,8 +339,8 @@ Let's see another example:
|
||||
|
||||
class CylindricalStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr CylindricalStorageTank(const quantity<isq::radius[m]>& radius,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
constexpr CylindricalStorageTank(const quantity<isq::radius[si::metre]>& radius,
|
||||
const quantity<isq::height[si::metre]>& height) :
|
||||
StorageTank(quantity_cast<horizontal_area>(std::numbers::pi * pow<2>(radius)),
|
||||
height)
|
||||
{
|
||||
@@ -348,9 +349,9 @@ Let's see another example:
|
||||
|
||||
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) :
|
||||
constexpr RectangularStorageTank(const quantity<horizontal_length[si::metre]>& length,
|
||||
const quantity<isq::width[si::metre]>& width,
|
||||
const quantity<isq::height[si::metre]>& height) :
|
||||
StorageTank(length * width, height)
|
||||
{
|
||||
}
|
||||
@@ -358,6 +359,7 @@ Let's see another example:
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
auto tank = RectangularStorageTank(horizontal_length(1'000 * mm),
|
||||
isq::width(500 * mm),
|
||||
isq::height(200 * mm));
|
||||
@@ -425,7 +427,6 @@ Let's see another example:
|
||||
#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
|
||||
@@ -437,11 +438,11 @@ Let's see another example:
|
||||
: quantity_spec<isq::area, horizontal_length * isq::width> {} horizontal_area;
|
||||
|
||||
class StorageTank {
|
||||
quantity<horizontal_area[m2]> base_;
|
||||
quantity<isq::height[m]> height_;
|
||||
quantity<horizontal_area[square(si::metre)]> base_;
|
||||
quantity<isq::height[si::metre]> height_;
|
||||
public:
|
||||
constexpr StorageTank(const quantity<horizontal_area[m2]>& base,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
constexpr StorageTank(const quantity<horizontal_area[square(si::metre)]>& base,
|
||||
const quantity<isq::height[si::metre]>& height) :
|
||||
base_(base), height_(height)
|
||||
{
|
||||
}
|
||||
@@ -451,8 +452,8 @@ Let's see another example:
|
||||
|
||||
class CylindricalStorageTank : public StorageTank {
|
||||
public:
|
||||
constexpr CylindricalStorageTank(const quantity<isq::radius[m]>& radius,
|
||||
const quantity<isq::height[m]>& height) :
|
||||
constexpr CylindricalStorageTank(const quantity<isq::radius[si::metre]>& radius,
|
||||
const quantity<isq::height[si::metre]>& height) :
|
||||
StorageTank(quantity_cast<horizontal_area>(std::numbers::pi * pow<2>(radius)),
|
||||
height)
|
||||
{
|
||||
@@ -461,9 +462,9 @@ Let's see another example:
|
||||
|
||||
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) :
|
||||
constexpr RectangularStorageTank(const quantity<horizontal_length[si::metre]>& length,
|
||||
const quantity<isq::width[si::metre]>& width,
|
||||
const quantity<isq::height[si::metre]>& height) :
|
||||
StorageTank(length * width, height)
|
||||
{
|
||||
}
|
||||
@@ -471,6 +472,7 @@ Let's see another example:
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace mp_units::si::unit_symbols;
|
||||
auto tank = RectangularStorageTank(horizontal_length(1'000 * mm),
|
||||
isq::width(500 * mm),
|
||||
isq::height(200 * mm));
|
||||
|
@@ -100,9 +100,6 @@ the `value_cast<U, Rep>(q)` which always returns the most precise result:
|
||||
|
||||
using Price = quantity_point<currency[us_dollar]>;
|
||||
using Scaled = quantity_point<currency[scaled_us_dollar], zeroth_point_origin<currency>, std::int64_t>;
|
||||
|
||||
Price price{12.95 * USD};
|
||||
Scaled spx = value_cast<USD_s, std::int64_t>(price);
|
||||
```
|
||||
|
||||
=== "C++20"
|
||||
@@ -123,9 +120,6 @@ the `value_cast<U, Rep>(q)` which always returns the most precise result:
|
||||
|
||||
using Price = quantity_point<currency[us_dollar]>;
|
||||
using Scaled = quantity_point<currency[scaled_us_dollar], zeroth_point_origin<currency>, std::int64_t>;
|
||||
|
||||
Price price{12.95 * USD};
|
||||
Scaled spx = value_cast<USD_s, std::int64_t>(price);
|
||||
```
|
||||
|
||||
=== "Portable"
|
||||
@@ -146,7 +140,10 @@ the `value_cast<U, Rep>(q)` which always returns the most precise result:
|
||||
|
||||
using Price = quantity_point<currency[us_dollar]>;
|
||||
using Scaled = quantity_point<currency[scaled_us_dollar], zeroth_point_origin<currency>, std::int64_t>;
|
||||
|
||||
Price price{12.95 * USD};
|
||||
Scaled spx = value_cast<USD_s, std::int64_t>(price);
|
||||
```
|
||||
|
||||
```cpp
|
||||
using namespace unit_symbols;
|
||||
Price price{12.95 * USD};
|
||||
Scaled spx = value_cast<USD_s, std::int64_t>(price);
|
||||
```
|
||||
|
Reference in New Issue
Block a user