| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | # Text Output
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Besides providing dimensional analysis and units conversions, the library also tries hard to print | 
					
						
							|  |  |  |  | any quantity in the most user-friendly way. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | !!! note | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  |     The library does not provide a text output for quantity points, as printing just a number and | 
					
						
							|  |  |  |  |     a unit is not enough to adequately describe a quantity point. Often, an additional postfix is | 
					
						
							|  |  |  |  |     required. | 
					
						
							| 
									
										
										
										
											2023-08-04 14:35:20 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  |     For example, the text output of `42 m` may mean many things and can also be confused with an | 
					
						
							|  |  |  |  |     output of a regular quantity. On the other hand, printing `42 m AMSL` for altitudes above mean | 
					
						
							|  |  |  |  |     sea level is a much better solution, but the library does not have enough information to print | 
					
						
							|  |  |  |  |     it that way by itself. | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | ## Derived unit symbols generation
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  | The library creates symbols for derived ones based on the provided definitions for base units. | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ### `unit_symbol_formatting`
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | `unit_symbol_formatting` is a data type describing the configuration of the symbol generation | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  | algorithm. It contains three orthogonal fields, each with a default value. | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | enum class text_encoding : std::int8_t { | 
					
						
							|  |  |  |  |   unicode,  // m³;  µs | 
					
						
							|  |  |  |  |   ascii,    // m^3; us | 
					
						
							|  |  |  |  |   default_encoding = unicode | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | enum class unit_symbol_solidus : std::int8_t { | 
					
						
							|  |  |  |  |   one_denominator,  // m/s;   kg m⁻¹ s⁻¹ | 
					
						
							|  |  |  |  |   always,           // m/s;   kg/(m s) | 
					
						
							|  |  |  |  |   never,            // m s⁻¹; kg m⁻¹ s⁻¹ | 
					
						
							|  |  |  |  |   default_denominator = one_denominator | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | enum class unit_symbol_separator : std::int8_t { | 
					
						
							|  |  |  |  |   space,          // kg m²/s² | 
					
						
							|  |  |  |  |   half_high_dot,  // kg⋅m²/s²  (valid only for unicode encoding) | 
					
						
							|  |  |  |  |   default_separator = space | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | struct unit_symbol_formatting { | 
					
						
							|  |  |  |  |   text_encoding encoding = text_encoding::default_encoding; | 
					
						
							|  |  |  |  |   unit_symbol_solidus solidus = unit_symbol_solidus::default_denominator; | 
					
						
							|  |  |  |  |   unit_symbol_separator separator = unit_symbol_separator::default_separator; | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### `unit_symbol()`
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Returns a `std::string_view` with the symbol of a unit for the provided configuration: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | template<unit_symbol_formatting fmt = unit_symbol_formatting{}, typename CharT = char, Unit U> | 
					
						
							|  |  |  |  | [[nodiscard]] consteval auto unit_symbol(U); | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | For example: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | static_assert(unit_symbol<{.solidus = unit_symbol_solidus::never, | 
					
						
							|  |  |  |  |                            .separator = unit_symbol_separator::half_high_dot}>(kg * m / s2) == "kg⋅m⋅s⁻²"); | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | !!! note | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     `std::string_view` is returned only when C++23 is available. Otherwise, an instance of a | 
					
						
							|  |  |  |  |     `basic_fixed_string` is being returned. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### `unit_symbol_to()`
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Inserts the generated unit symbol to the output text iterator at runtime based on the provided | 
					
						
							|  |  |  |  | configuration. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | template<typename CharT = char, std::output_iterator<CharT> Out, Unit U> | 
					
						
							|  |  |  |  | constexpr Out unit_symbol_to(Out out, U u, unit_symbol_formatting fmt = unit_symbol_formatting{}); | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | For example: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | std::string txt; | 
					
						
							|  |  |  |  | unit_symbol_to(std::back_inserter(txt), kg * m / s2, | 
					
						
							|  |  |  |  |                {.solidus = unit_symbol_solidus::never, .separator = unit_symbol_separator::half_high_dot}); | 
					
						
							|  |  |  |  | std::cout << txt << "\n"; | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | The above prints: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```text | 
					
						
							|  |  |  |  | kg⋅m⋅s⁻² | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## Quantity text output
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ### Customization point
 | 
					
						
							| 
									
										
										
										
											2023-09-04 11:09:40 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-29 11:21:27 +02:00
										 |  |  |  | The [SI Brochure](../../appendix/references.md#SIBrochure) says: | 
					
						
							| 
									
										
										
										
											2023-09-04 11:09:40 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | !!! quote "SI Brochure" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     The numerical value always precedes the unit and a space is always used to separate the unit from | 
					
						
							|  |  |  |  |     the number. ... The only exceptions to this rule are for the unit symbols for degree, minute and | 
					
						
							|  |  |  |  |     second for plane angle, `°`, `′` and `″`, respectively, for which no space is left between the | 
					
						
							|  |  |  |  |     numerical value and the unit symbol. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | To support the above, the library exposes `space_before_unit_symbol` customization point. By default, | 
					
						
							|  |  |  |  | its value is `true` for all the units, so the space between a number and a unit will be present in the | 
					
						
							|  |  |  |  | output text. To change this behavior, we have to provide a partial specialization for a specific unit: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | template<> | 
					
						
							|  |  |  |  | inline constexpr bool space_before_unit_symbol<non_si::degree> = false; | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | !!! note | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  |     The above works only for [the default formatting](#default-formatting). In case we provide our | 
					
						
							|  |  |  |  |     own format specification (e.g., `std::format("{:%Q %q}", q)`), the library will always obey this | 
					
						
							| 
									
										
										
										
											2023-09-04 11:09:40 +02:00
										 |  |  |  |     specification for all the units (no matter of what is the actual value of the | 
					
						
							|  |  |  |  |     `space_before_unit_symbol` customization point) and the separating space will always be present | 
					
						
							|  |  |  |  |     in this case. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | ### Output streams
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | !!! tip | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     The output streaming support is opt-in and can be enabled by including the `<mp-units/ostream.h>` | 
					
						
							|  |  |  |  |     header file. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | The easiest way to print a quantity is to provide its object to the output stream: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | using namespace mp_units; | 
					
						
							|  |  |  |  | using namespace mp_units::si::unit_symbols; | 
					
						
							|  |  |  |  | using namespace mp_units::international::unit_symbols; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | const QuantityOf<isq::speed> auto v1 = avg_speed(220. * km, 2 * h); | 
					
						
							|  |  |  |  | const QuantityOf<isq::speed> auto v2 = avg_speed(140. * mi, 2 * h); | 
					
						
							|  |  |  |  | std::cout << v1 << '\n';  // 110 km/h | 
					
						
							|  |  |  |  | std::cout << v2 << '\n';  // 70 mi/h | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  |  | The text output will always print the [value of a quantity](../../appendix/glossary.md#quantity-value) | 
					
						
							|  |  |  |  | typically followed by a space and then the symbol of a [unit](../../appendix/glossary.md#unit) | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | associated with this quantity. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-25 14:14:26 +02:00
										 |  |  |  | !!! important "Important: Don't assume a unit" | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  |     Remember that when we deal with a quantity of an "unknown" (e.g., `auto`) type, it is a good | 
					
						
							| 
									
										
										
										
											2023-10-25 14:14:26 +02:00
										 |  |  |  |     practice to always [convert the unit to the expected one](value_conversions.md#value-conversions) | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  |     before passing it to the text output: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     ```cpp | 
					
						
							| 
									
										
										
										
											2023-09-13 10:44:50 +02:00
										 |  |  |  |     std::cout << v1.in(km / h) << '\n';       // 110 km/h | 
					
						
							|  |  |  |  |     std::cout << v1.force_in(m / s) << '\n';  // 30.5556 m/s | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  |     ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | #### Output stream formatting
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  | Only basic formatting can be applied to output streams. It includes control over width, fill, | 
					
						
							| 
									
										
										
										
											2023-11-30 09:27:43 +01:00
										 |  |  |  | and alignment of the entire quantity and formatting of a quantity numerical value according | 
					
						
							|  |  |  |  | to the general C++ rules: | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | std::cout << "|" << std::setw(10) << 123 * m << "|\n";                       // |     123 m| | 
					
						
							|  |  |  |  | std::cout << "|" << std::setw(10) << std::left << 123 * m << "|\n";          // |123 m     | | 
					
						
							|  |  |  |  | std::cout << "|" << std::setw(10) << std::setfill('*') << 123 * m << "|\n";  // |123 m*****| | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | !!! note | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     To have more control over the formatting of the quantity that is printed with the output | 
					
						
							|  |  |  |  |     stream just use `std::cout << std::format(...)`. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | ### `std::format`
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | !!! tip | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     The text formatting facility support is opt-in and can be enabled by including the | 
					
						
							|  |  |  |  |     `<mp-units/format.h>` header file. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | The **mp-units** library provides custom formatters for `std::format` facility which allows | 
					
						
							|  |  |  |  | fine-grained control over what and how it is being printed in the text output. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | #### Grammar
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | ```ebnf | 
					
						
							|  |  |  |  | quantity-format-spec  ::=  [fill-and-align] [width] [quantity-specs] | 
					
						
							|  |  |  |  | quantity-specs        ::=  conversion-spec | 
					
						
							|  |  |  |  |                            quantity-specs conversion-spec | 
					
						
							|  |  |  |  |                            quantity-specs literal-char | 
					
						
							|  |  |  |  | literal-char          ::=  any character other than '{' or '}' | 
					
						
							|  |  |  |  | conversion-spec       ::=  '%' type | 
					
						
							|  |  |  |  | type                  ::=  [rep-modifier] 'Q' | 
					
						
							|  |  |  |  |                            [unit-modifier] 'q' | 
					
						
							|  |  |  |  | rep-modifier          ::=  [sign] [#] [precision] [L] [rep-type] | 
					
						
							|  |  |  |  | rep-type              ::=  one of | 
					
						
							|  |  |  |  |                            a A b B d e E f F g G o x X | 
					
						
							|  |  |  |  | unit-modifier         ::=  [text-encoding] [unit-symbol-solidus] [unit-symbol-separator] | 
					
						
							|  |  |  |  |                            [text-encoding] [unit-symbol-separator] [unit-symbol-solidus] | 
					
						
							|  |  |  |  |                            [unit-symbol-solidus] [text-encoding] [unit-symbol-separator] | 
					
						
							|  |  |  |  |                            [unit-symbol-solidus] [unit-symbol-separator] [text-encoding] | 
					
						
							|  |  |  |  |                            [unit-symbol-separator] [text-encoding] [unit-symbol-solidus] | 
					
						
							| 
									
										
										
										
											2023-12-27 15:51:39 +01:00
										 |  |  |  |                            [unit-symbol-separator] [unit-symbol-solidus] [text-encoding] | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | text-encoding         ::=  one of | 
					
						
							|  |  |  |  |                            U A | 
					
						
							|  |  |  |  | unit-symbol-solidus   ::=  one of | 
					
						
							|  |  |  |  |                            o a n | 
					
						
							|  |  |  |  | unit-symbol-separator ::=  one of | 
					
						
							|  |  |  |  |                            s d | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | In the above grammar: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | - `fill-and-align`, `width`, `sign`, `#`, `precision`, and `L` tokens, as well as the individual | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  |   tokens of `rep-type` are defined in the [format.string.std](https://wg21.link/format.string.std) | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  |   chapter of the C++ standard specification, | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | - tokens `Q` and `q` of `type` are described in the [time.format](https://wg21.link/time.format) | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  |   chapter of the C++ standard specification, | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | - `text-encoding` tokens specify the unit text encoding: | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  |  |     - `U` (default) uses the **Unicode** symbols defined by the [SI](../../appendix/glossary.md#si) | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  |       specification (e.g., `m³`, `µs`) | 
					
						
							|  |  |  |  |     - `A` token forces non-standard **ASCII**-only output (e.g., `m^3`, `us`) | 
					
						
							|  |  |  |  | - `unit-symbol-solidus` tokens specify how the division of units should look like: | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  |     - `o` (default) outputs `/` only when there is only **one** unit in the denominator, otherwise | 
					
						
							|  |  |  |  |       negative exponents are printed (e.g., `m/s`, `kg m⁻¹ s⁻¹`) | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  |     - `a` **always** uses solidus (e.g., `m/s`, `kg/(m s)`) | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  |     - `n` **never** prints solidus, which means that negative exponents are always used | 
					
						
							|  |  |  |  |       (e.g., `m s⁻¹`, `kg m⁻¹ s⁻¹`) | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | - `unit-symbol-separator` tokens specify how multiplied unit symbols should be separated: | 
					
						
							|  |  |  |  |     - `s` (default) uses **space** as a separator (e.g., `kg m²/s²`) | 
					
						
							|  |  |  |  |     - `d` uses half-high **dot** (`⋅`) as a separator (e.g., `kg⋅m²/s²`) | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | #### Default formatting
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | To format `quantity` values, the formatting facility uses `quantity-format-spec`. If left empty, | 
					
						
							| 
									
										
										
										
											2023-11-30 09:59:55 +01:00
										 |  |  |  | the default formatting is applied. The same default formatting is also applied to the output streams. | 
					
						
							|  |  |  |  | This is why the following code lines produce the same output: | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | std::cout << "Distance: " << 123 * km << "\n"; | 
					
						
							|  |  |  |  | std::cout << std::format("Distance: {}\n", 123 * km); | 
					
						
							|  |  |  |  | std::cout << std::format("Distance: {:%Q %q}\n", 123 * km); | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 09:59:55 +01:00
										 |  |  |  | !!! note | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  |     For some quantities, the `{:%Q %q}` format may provide a different output than the default one. | 
					
						
							|  |  |  |  |     It will happen, for example for: | 
					
						
							| 
									
										
										
										
											2023-11-30 09:59:55 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |     - units for which [`space_before_unit_symbol`](#customization-point) customization point is set | 
					
						
							|  |  |  |  |       to `false`, | 
					
						
							|  |  |  |  |     - quantities of dimension one with a unit one. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | #### Controlling width, fill, and alignment
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | To control width, fill, and alignment, the C++ standard grammar tokens `fill-and-align` and `width` | 
					
						
							|  |  |  |  | are being used, and they treat a quantity value and symbol as a contiguous text: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | std::println("|{:0}|", 123 * m);     // |123 m| | 
					
						
							|  |  |  |  | std::println("|{:10}|", 123 * m);    // |     123 m| | 
					
						
							|  |  |  |  | std::println("|{:<10}|", 123 * m);   // |123 m     | | 
					
						
							|  |  |  |  | std::println("|{:>10}|", 123 * m);   // |     123 m| | 
					
						
							|  |  |  |  | std::println("|{:^10}|", 123 * m);   // |  123 m   | | 
					
						
							|  |  |  |  | std::println("|{:*<10}|", 123 * m);  // |123 m*****| | 
					
						
							|  |  |  |  | std::println("|{:*>10}|", 123 * m);  // |*****123 m| | 
					
						
							|  |  |  |  | std::println("|{:*^10}|", 123 * m);  // |**123 m***| | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | !!! note | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-25 21:27:01 +02:00
										 |  |  |  |     [`std::println` is a C++23 facility](https://en.cppreference.com/w/cpp/io/print). In case we | 
					
						
							|  |  |  |  |     do not have access to C++23, we can obtain the same output with: | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  |     ```cpp | 
					
						
							|  |  |  |  |     std::cout << std::format("<format-string>\n", <format-args>); | 
					
						
							|  |  |  |  |     ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | #### Quantity value, symbol, or both?
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | The user can easily decide to either print a whole quantity (value and symbol) or only its parts. | 
					
						
							|  |  |  |  | Also, a custom style of quantity formatting might be applied: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | std::println("{:%Q}", 123 * km);    // 123 | 
					
						
							|  |  |  |  | std::println("{:%q}", 123 * km);    // km | 
					
						
							|  |  |  |  | std::println("{:%Q%q}", 123 * km);  // 123km | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | #### Quantity value formatting
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | `sign` token allows us to specify how the value's sign is being printed: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | std::println("{0:%Q %q},{0:%+Q %q},{0:%-Q %q},{0:% Q %q}", 1 * m);   // 1 m,+1 m,1 m, 1 m | 
					
						
							|  |  |  |  | std::println("{0:%Q %q},{0:%+Q %q},{0:%-Q %q},{0:% Q %q}", -1 * m);  // -1 m,-1 m,-1 m,-1 m | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | where: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | - `+` indicates that a sign should be used for both non-negative and negative numbers, | 
					
						
							|  |  |  |  | - `-` indicates that a sign should be used for negative numbers and negative zero only | 
					
						
							|  |  |  |  |   (this is the default behavior), | 
					
						
							|  |  |  |  | - `<space>` indicates that a leading space should be used for non-negative numbers other | 
					
						
							|  |  |  |  |   than negative zero, and a minus sign for negative numbers and negative zero. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | `precision` token is allowed only for floating-point representation types: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | std::println("{:%.0Q %q}", 1.2345 * m);  // 1 m | 
					
						
							|  |  |  |  | std::println("{:%.1Q %q}", 1.2345 * m);  // 1.2 m | 
					
						
							|  |  |  |  | std::println("{:%.2Q %q}", 1.2345 * m);  // 1.23 m | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | `rep-type` specifies how a value of the representation type is being printed. | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | For integral types: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | std::println("{:%bQ %q}", 42 * m);    // 101010 m | 
					
						
							|  |  |  |  | std::println("{:%BQ %q}", 42 * m);    // 101010 m | 
					
						
							|  |  |  |  | std::println("{:%dQ %q}", 42 * m);    // 42 m | 
					
						
							|  |  |  |  | std::println("{:%oQ %q}", 42 * m);    // 52 m | 
					
						
							|  |  |  |  | std::println("{:%xQ %q}", 42 * m);    // 2a m | 
					
						
							|  |  |  |  | std::println("{:%XQ %q}", 42 * m);    // 2A m | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | The above can be printed in an alternate version thanks to the `#` token: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | std::println("{:%#bQ %q}", 42 * m);   // 0b101010 m | 
					
						
							|  |  |  |  | std::println("{:%#BQ %q}", 42 * m);   // 0B101010 m | 
					
						
							|  |  |  |  | std::println("{:%#oQ %q}", 42 * m);   // 052 m | 
					
						
							|  |  |  |  | std::println("{:%#xQ %q}", 42 * m);   // 0x2a m | 
					
						
							|  |  |  |  | std::println("{:%#XQ %q}", 42 * m);   // 0X2A m | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | For floating-point values, the `rep-type` token works as follows: | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | std::println("{:%aQ %q}",   1.2345678 * m);      // 0x1.3c0ca2a5b1d5dp+0 m | 
					
						
							|  |  |  |  | std::println("{:%.3aQ %q}", 1.2345678 * m);      // 0x1.3c1p+0 m | 
					
						
							|  |  |  |  | std::println("{:%AQ %q}",   1.2345678 * m);      // 0X1.3C0CA2A5B1D5DP+0 m | 
					
						
							|  |  |  |  | std::println("{:%.3AQ %q}", 1.2345678 * m);      // 0X1.3C1P+0 m | 
					
						
							|  |  |  |  | std::println("{:%eQ %q}",   1.2345678 * m);      // 1.234568e+00 m | 
					
						
							|  |  |  |  | std::println("{:%.3eQ %q}", 1.2345678 * m);      // 1.235e+00 m | 
					
						
							|  |  |  |  | std::println("{:%EQ %q}",   1.2345678 * m);      // 1.234568E+00 m | 
					
						
							|  |  |  |  | std::println("{:%.3EQ %q}", 1.2345678 * m);      // 1.235E+00 m | 
					
						
							|  |  |  |  | std::println("{:%gQ %q}",   1.2345678 * m);      // 1.23457 m | 
					
						
							|  |  |  |  | std::println("{:%gQ %q}",   1.2345678e8 * m);    // 1.23457e+08 m | 
					
						
							|  |  |  |  | std::println("{:%.3gQ %q}", 1.2345678 * m);      // 1.23 m | 
					
						
							|  |  |  |  | std::println("{:%.3gQ %q}", 1.2345678e8 * m);    // 1.23e+08 m | 
					
						
							|  |  |  |  | std::println("{:%GQ %q}",   1.2345678 * m);      // 1.23457 m | 
					
						
							|  |  |  |  | std::println("{:%GQ %q}",   1.2345678e8 * m);    // 1.23457E+08 m | 
					
						
							|  |  |  |  | std::println("{:%.3GQ %q}", 1.2345678 * m);      // 1.23 m | 
					
						
							|  |  |  |  | std::println("{:%.3GQ %q}", 1.2345678e8 * m);    // 1.23E+08 m | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 10:53:29 +01:00
										 |  |  |  | #### Unit symbol formatting
 | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | Unit symbols of some quantities are specified to use Unicode signs by the | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | [SI](../../appendix/glossary.md#si) (e.g., `Ω` symbol for the resistance quantity). The **mp-units** | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | library follows this by default. From the engineering point of view, sometimes Unicode text might | 
					
						
							|  |  |  |  | not be the best solution as terminals of many (especially embedded) devices are ASCII-only. | 
					
						
							|  |  |  |  | In such a case, the unit symbol can be forced to be printed using ASCII-only characters thanks to | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  | the `text-encoding` token: | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							|  |  |  |  | std::println("{}", 10 * si::ohm);             // 10 Ω | 
					
						
							|  |  |  |  | std::println("{:%Q %Aq}", 10 * si::ohm);      // 10 ohm | 
					
						
							|  |  |  |  | std::println("{}", 125 * us);                 // 125 µs | 
					
						
							|  |  |  |  | std::println("{:%Q %Aq}", 125 * us);          // 125 us | 
					
						
							|  |  |  |  | std::println("{}", 9.8 * (m / s2));           // 9.8 m/s² | 
					
						
							|  |  |  |  | std::println("{:%Q %Aq}", 9.8 * (m / s2));    // 9.8 m/s^2 | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-03 21:23:34 +02:00
										 |  |  |  | Additionally, both [ISQ](../../appendix/glossary.md#isq) and [SI](../../appendix/glossary.md#si) | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | leave some freedom on how to print unit symbols. This is why two additional tokens were introduced. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | `unit-symbol-solidus` specifies how the division of units should look like. By default, | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | `/` will be used only when the denominator contains only one unit. However, with the `a` or `n` | 
					
						
							|  |  |  |  | options, we can force the facility to print the `/` character always (even when there are more units | 
					
						
							|  |  |  |  | in the denominator), or never in which case a parenthesis will be added to enclose all denominator | 
					
						
							|  |  |  |  | units. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							| 
									
										
										
										
											2023-09-29 21:40:24 -06:00
										 |  |  |  | std::println("{:%Q %q}", 1 * m / s);         // 1 m/s | 
					
						
							|  |  |  |  | std::println("{:%Q %q}", 1 * kg / m / s2);   // 1 kg m⁻¹ s⁻² | 
					
						
							|  |  |  |  | std::println("{:%Q %aq}", 1 * m / s);        // 1 m/s | 
					
						
							|  |  |  |  | std::println("{:%Q %aq}", 1 * kg / m / s2);  // 1 kg/(m s²) | 
					
						
							|  |  |  |  | std::println("{:%Q %nq}", 1 * m / s);        // 1 m s⁻¹ | 
					
						
							|  |  |  |  | std::println("{:%Q %nq}", 1 * kg / m / s2);  // 1 kg m⁻¹ s⁻² | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Also, there are a few options to separate the units being multiplied: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | !!! quote "ISO 80000-1" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     When symbols for quantities are combined in a product of two or more quantities, this combination | 
					
						
							|  |  |  |  |     is indicated in one of the following ways: `ab`, `a b`, `a · b`, `a × b` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     _NOTE 1_ In some fields, e.g., vector algebra, distinction is made between `a ∙ b` and `a × b`. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  | As of today, the **mp-units** library only supports `a b` and `a · b`. Additionally, | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | we decided that the extraneous space in the latter case makes the result too verbose, so we decided | 
					
						
							|  |  |  |  | to just use the `·` symbol as a separator. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | !!! note | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:34:06 +01:00
										 |  |  |  |     Please let us know if you require more formatting options here. | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-27 11:26:56 +01:00
										 |  |  |  | The `unit-symbol-separator` token allows us to obtain the following outputs: | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | ```cpp | 
					
						
							| 
									
										
										
										
											2023-09-29 21:40:24 -06:00
										 |  |  |  | std::println("{:%Q %q}", 1 * kg * m2 / s2);   // 1 kg m²/s² | 
					
						
							|  |  |  |  | std::println("{:%Q %dq}", 1 * kg * m2 / s2);  // 1 kg⋅m²/s² | 
					
						
							| 
									
										
										
										
											2023-07-24 17:36:49 +02:00
										 |  |  |  | ``` |