The unit travels with the value
log("speed: {} m/s", speed) hard-codes a claim about speed that the type system never checks. Two refactors later someone switches the calculation to km/h, the log line still reads m/s, and the next person to open it loses an afternoon debugging the wrong number. Most unit bugs I chase end up in a log file, and a format string is the easiest place to plant one.
The rest of this series moved the unit into the value’s type. Once it lives there, the printed text should come from the type too.
std::format reads the unit off the type
mp-units quantities plug straight into std::format. The default spec prints the value and the unit symbol together. A quantity-specific grammar lets you address the Number and Unit parts of the output separately when you need to control precision:
{} prints 120 km/h, and the symbol comes from the type, so it stays honest even though the format string never names a unit. {::N[.2f]} applies .2f to the numeric part alone; the same spec prints 120.00 km/h for one quantity and 33.33 m/s for another, because the precision request and the unit are handled independently. The marathon line makes the last point: convert the quantity, and every piece of text downstream converts with it.
Episode 1 showed units guarding arithmetic. This one shows them guarding the output: logs, telemetry, UI labels. The Mars Climate Orbiter report put the fault at exactly that boundary, in files one team’s software handed to another’s, where the mismatch sat undetected.
P3045 proposes moving mp-units into the standard library, on the C++29 timeline.
Sources: mp-units documentation: text output.