diff --git a/docs/getting_started/faq.md b/docs/getting_started/faq.md index fa9c29c7..37d4edd9 100644 --- a/docs/getting_started/faq.md +++ b/docs/getting_started/faq.md @@ -139,6 +139,71 @@ all the properties of scaled units and is consistent with the rest of the librar [the Dimensionless Quantities chapter](../users_guide/framework_basics/dimensionless_quantities.md). +## Why derived units order is not preserved from the multiplication? + +It might be surprising, but the quantities and units multiplication order does not impact the order +of components in the derived unit. Let's try the following example: + +```cpp +std::println("{}", 42 * kW * h); +constexpr auto kWh = kW * h; +std::println("{}", 42 * kWh); +``` + +The above prints: + +```text +42 h kW +42 h kW +``` + +Some users could expect to see `42 kWh` or `42 kW h` in the output. It is not the case and for +a very good reason. As stated in +[Simplifying the resulting expression templates](../users_guide/framework_basics/interface_introduction.md#simplifying-the-resulting-expression-templates), +to be able to reason about and simplify units, the library needs to order them in an appropriate +order. + +Maybe this default order could be improved a bit, but according to international standards, +there is no generic ordering rule. Various quantities use different, often domain-specific, +ordering of derived unit components. + +Let's see what [SI](../appendix/references.md#SIBrochure) says here: + +| Derived quantity | Symbol | Derived unit expressed in terms of base units | +|----------------------------|:------:|:---------------------------------------------:| +| _electric field strength_ | V m⁻¹ | kg m s⁻³ A⁻¹ | +| _electric charge density_ | C m⁻³ | A s m⁻³ | +| _exposure (x- and γ-rays)_ | C kg⁻¹ | A s kg⁻¹ | + +However, there is a workaround. A user can define its own named unit for a derived unit and provide +the custom symbol text that suits the project's requirements. For example, the above case could be +addressed with: + +```cpp +inline constexpr struct kilowatt_hour final : named_unit<"kWh", kW * h> {} kilowatt_hour; +inline constexpr auto kWh = kilowatt_hour; +``` + +With the above, we can refactor the above code to: + +```cpp +std::println("{}", 42 * kWh); +std::println("{}", (42 * kW * h).in(kWh)); +``` + +Both lines will produce an expected "42 kWh" unit in the output. + +!!! important + + Please note that this makes the entire "kWh" a single, indivisible entity that is not subject + to simplification rules. This means that `42 * kWh / (2 * h)` will result with `21 kWh/h` + rather than `21 kW`. To get the latter, the user needs to explicitly provide a new derived unit: + + ```cpp + std::println("{}", (42 * kWh / (2 * h)).in(kW)); + ``` + + ## Why do the identifiers for concepts in the library use `CamelCase`? Initially, C++20 was meant to use `CamelCase` for all the concept identifiers. All the concepts