diff --git a/docs/getting_started/quick_start.md b/docs/getting_started/quick_start.md index e66de005..55b2872d 100644 --- a/docs/getting_started/quick_start.md +++ b/docs/getting_started/quick_start.md @@ -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: diff --git a/docs/users_guide/framework_basics/simple_and_typed_quantities.md b/docs/users_guide/framework_basics/simple_and_typed_quantities.md index 864289eb..35e4f83e 100644 --- a/docs/users_guide/framework_basics/simple_and_typed_quantities.md +++ b/docs/users_guide/framework_basics/simple_and_typed_quantities.md @@ -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 avg_speed(quantity dist, - quantity time) + constexpr quantity avg_speed(quantity dist, + quantity 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 using namespace mp_units; - using namespace mp_units::si::unit_symbols; - constexpr quantity avg_speed(quantity dist, - quantity time) + constexpr quantity avg_speed(quantity dist, + quantity 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 {} horizontal_area; class StorageTank { - quantity base_; - quantity height_; + quantity base_; + quantity height_; public: - constexpr StorageTank(const quantity& base, - const quantity& height) : + constexpr StorageTank(const quantity& base, + const quantity& height) : base_(base), height_(height) { } @@ -338,8 +339,8 @@ Let's see another example: class CylindricalStorageTank : public StorageTank { public: - constexpr CylindricalStorageTank(const quantity& radius, - const quantity& height) : + constexpr CylindricalStorageTank(const quantity& radius, + const quantity& height) : StorageTank(quantity_cast(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& length, - const quantity& width, - const quantity& height) : + constexpr RectangularStorageTank(const quantity& length, + const quantity& width, + const quantity& 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 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 {} horizontal_area; class StorageTank { - quantity base_; - quantity height_; + quantity base_; + quantity height_; public: - constexpr StorageTank(const quantity& base, - const quantity& height) : + constexpr StorageTank(const quantity& base, + const quantity& height) : base_(base), height_(height) { } @@ -451,8 +452,8 @@ Let's see another example: class CylindricalStorageTank : public StorageTank { public: - constexpr CylindricalStorageTank(const quantity& radius, - const quantity& height) : + constexpr CylindricalStorageTank(const quantity& radius, + const quantity& height) : StorageTank(quantity_cast(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& length, - const quantity& width, - const quantity& height) : + constexpr RectangularStorageTank(const quantity& length, + const quantity& width, + const quantity& 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)); diff --git a/docs/users_guide/framework_basics/value_conversions.md b/docs/users_guide/framework_basics/value_conversions.md index e31575ca..bed6e928 100644 --- a/docs/users_guide/framework_basics/value_conversions.md +++ b/docs/users_guide/framework_basics/value_conversions.md @@ -100,9 +100,6 @@ the `value_cast(q)` which always returns the most precise result: using Price = quantity_point; using Scaled = quantity_point, std::int64_t>; - - Price price{12.95 * USD}; - Scaled spx = value_cast(price); ``` === "C++20" @@ -123,9 +120,6 @@ the `value_cast(q)` which always returns the most precise result: using Price = quantity_point; using Scaled = quantity_point, std::int64_t>; - - Price price{12.95 * USD}; - Scaled spx = value_cast(price); ``` === "Portable" @@ -146,7 +140,10 @@ the `value_cast(q)` which always returns the most precise result: using Price = quantity_point; using Scaled = quantity_point, std::int64_t>; - - Price price{12.95 * USD}; - Scaled spx = value_cast(price); ``` + +```cpp +using namespace unit_symbols; +Price price{12.95 * USD}; +Scaled spx = value_cast(price); +```