Skip to content

2026

If they can't find you, the code doesn't matter

You need a units library for C++. You search GitHub for "units" and get a wall of repositories, all some variation of the same word, by different authors, with no obvious way to tell which one is alive, which one is serious, and which one will still be maintained next year. You pick one almost at random, or you give up and write your own. The library you needed might have been right there. You just could not find it, or could not tell it apart from the noise.

Introducing Photometric Conditions

A "1000 lm" LED lamp and a "1000 lm" low-pressure sodium lamp do not look equally bright at night. The number on both boxes is a photopic value: it weights the lamp's spectrum with \(V(\lambda)\), the spectral sensitivity of the eye's cone cells, which drive vision in daylight. At night, rod cells take over, the sensitivity curve shifts towards blue (\(V'(\lambda)\)), and the same two lamps deliver roughly 2000 and 250 scotopic lumens respectively. Both figures are luminous fluxes expressed in lumens, and a program that adds or compares them computes a result that is wrong by up to a factor of eight:

auto led = 1000. * lm;     // photopic value from the datasheet
auto sodium = 250. * lm;   // scotopic value from a night-visibility model
auto total = led + sodium; // compiles everywhere, means nothing

To the best of our knowledge, no units library catches this today, because every one of them (including mp-units until now) models a lumen as a lumen. This post introduces photometric conditions: a way to keep photopic, scotopic, mesopic, and custom quantities in separate quantity hierarchies, so that the mistake above breaks at compile time, while everything the physics does allow keeps working.

Measurement uncertainty and measured constants

When you write constexpr double G = 6.674e-11; in your code, the type says the value is exact, and it is not. The Newtonian constant of gravitation is one of the least precisely known constants in physics. CODATA 2018 lists it as 6.674 30(15) × 10⁻¹¹ m³ kg⁻¹ s⁻², and the (15) means the fifth significant digit is already uncertain. Only four digits of G are actually known. Every result derived from that double inherits an uncertainty that the program neither tracks nor reports, and nothing stops it from printing ten significant digits of a solar mass computed from a constant that guarantees four.

mp-units now has a way to model this. This post introduces the uncertain<T> representation type, the standard_uncertainty and relative_standard_uncertainty metadata for measured constants, and the measurement_of helper that connects them.

Introducing Logarithmic Quantities and Units

Decibels are everywhere in engineering. Signal levels in dBm, sound pressure in dB SPL, voltage gain in dB, filter slopes in dB/octave. The neper, pH, and stellar magnitude share the same structure. Yet, to the best of our knowledge, no general-purpose units library models logarithmic quantities correctly. Most do not model them at all. The few that do treat a decibel as a non-linear scale or an offset unit, and that choice gets the arithmetic wrong in ways that compile silently.

This article is a request for feedback. We believe we have a correct design, derived from the same affine-space model we introduced for absolute quantities. It also aims to stay consistent with the ISO/IEC 80000 standards: especially IEC 80000-15:2026, Logarithmic quantities and their units, which consolidates the logarithmic-quantity rules once held in ISO 80000-1:2009 (Annex C); together with ISO 80000-2 (the logarithm functions lb, ln, lg), ISO 80000-8 (acoustics), and IEC 80000-13 (information theory). We have read those against this design, cite them throughout, and call out the one place we knowingly diverge from them (Open Question 5).

This post describes the design in full, from the quantity spec to the named units, the arithmetic, the conversions, and every domain we surveyed. Then it lays out the open questions, each with the alternatives we considered and our current preference. Before we implement any of this in mp-units, we want the people who work with these quantities to tell us where we are wrong.

Bringing Safety to HEP

High-Energy Physics software runs detector geometries spanning millions of volumes, tracking and reconstruction algorithms, and multi-day simulations on the Grid. A single silent unit mismatch in a double can invalidate an entire analysis or produce detector geometry that is 10× the wrong size. This post shows how mp-units can bring compile-time safety to HEP codebases (including a dedicated HEP system of quantities and units) and how large projects like ATLAS can adopt it incrementally.

Why a Quantity Has a Character

A few years ago at CppCon, an engineer who works with electrical power systems every day stopped me after a talk. He told me that his team confuses active power, reactive power, apparent power, and complex power all the time, and that the mistake is easy to make and expensive to find. Then he said the sentence that has stuck with me since: a units library that will not make those four incompatible types is of no use in his industry.

He is right, and the same confusion shows up in other domains.


Note: Revised on July 5, 2026 to incorporate the feedback in the comments below.

Preventing Integer Overflow in Physical Computations

Integers overflow. What is more surprising is how easily overflow can hide behind the abstraction of a units library.

Most developers immediately think of explicit or implicit scaling operations: calling .in(unit) to convert a quantity, constructing a quantity from a different unit, or assigning between quantities with different units. These are indeed places where overflow can occur, and the library cannot prevent it at compile time when the values are only known at runtime. But at least these operations are visible in your code: you wrote the conversion, you asked for the scaling, and you can reason about whether the multiplication or division might overflow your integer type.

The harder problem is what happens when you do not ask for a conversion.

When you write 1 * m + 1 * ft, the library must automatically convert both operands to a common unit before performing the addition. That conversion, which you never explicitly requested, involves multiplication or division by scaling factors. With integer representations, those scaling operations can overflow silently, producing garbage results that propagate through your calculations undetected.

No compile-time programming can prevent this. The values are only known at runtime. But very few libraries provide proper tools to detect it.