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.
I can tell you exactly how many stars mp-units has. The number is right there on the GitHub
page and on my docs site, it updates in real time, and I can plot it against every competing
units library on a single chart. What I can't tell you, even roughly, is how many people
actually use it.
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:
autoled=1000.*lm;// photopic value from the datasheetautosodium=250.*lm;// scotopic value from a night-visibility modelautototal=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.
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.
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.
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.
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.
How do units and linear algebra fit together? We get that question often. Two different
questions hide inside it, and they have different solutions.
The occasion for answering now is concrete: mp-units ships opt-in integrations that let
mainstream linear algebra libraries (Eigen,
GLM, and Blaze)
act directly as the representation type of a quantity.
The Brno 2026 ISO C++ Committee meeting has just finished. It was the first
meeting of the C++29 cycle, and quite a lot already landed in the working draft.
Below are the highlights voted in during the closing plenary and an update on the
quantities and units standardization effort.
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.