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.
Integers overflow. That is not a controversial statement. What is 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 far more insidious problem is what happens when you don't 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.
This article explains why that limitation is real, how other libraries have
tried to work around it, and what mp-units provides to close the gap as
tightly as the language allows.
Physical units libraries have always been very good at preventing dimensional
errors and unit mismatches. But there is a category of correctness that they have
universally ignored: domain constraints on quantity point values.
A latitude is not just a length divided by a radius. It is a value that lives in
\([-90°, +90°]\); anything outside that range is physically meaningless. An angle
used in bearing navigation wraps cyclically around a circle; treating it as an
unbounded real number ignores a fundamental property of the domain. A clinical
body-temperature sensor should reject a reading of \(44\ \mathrm{°C}\) at the API
boundary, not silently pass it downstream.
Type-level constraint enforcement for quantity points with this level of
flexibility is a relatively unexplored area in mainstream physical units libraries.
The approach we present here is novel and experimental — we are certain there are
edge cases and design considerations we haven't yet discovered.
This article describes the motivation in depth, the design we arrived at, and
the open questions we would love the community's help to answer.
Physical quantities and units libraries exist primarily to prevent errors at compile time.
However, not all libraries provide the same level of safety. Some focus only on dimensional
analysis and unit conversions, while others go further to prevent representation errors,
semantic misuse of same-dimension quantities, and even errors in the mathematical structure
of equations.
This article explores six distinct safety levels that a comprehensive quantities and units
library can provide. We'll examine each level in detail with practical examples, then compare
how leading C++ libraries and units libraries from other languages perform across these
safety dimensions. Finally, we'll analyze the performance and memory costs associated
with different approaches, helping you understand the trade-offs between safety guarantees
and runtime efficiency.
We'll pay particular attention to the upper safety levels—especially quantity kind
safety (distinguishing dimensionally equivalent concepts such as work vs. torque, or
Hz vs. Bq) and quantity safety (enforcing correct quantity hierarchies and
scalar/vector/tensor mathematical rules)—which are well-established concepts in metrology
and physics, yet remain widely overlooked in the C++ ecosystem. Most units library authors
and users simply do not realize these guarantees are achievable, or how much they matter
in practice. These levels go well beyond dimensional analysis, preventing subtle semantic
errors that unit conversions alone cannot catch, and are essential for realizing truly
strongly-typed numerics in C++.
Until now, mp-units forced users to choose between points (no arithmetic) and deltas
(no physical semantics) — missing the most common case: a non-negative absolute amount.
An absolute quantity represents an absolute amount of a physical property —
measured from a true, physically meaningful zero. Examples include mass in kilograms,
temperature in Kelvin, or length in meters (as a size, not a position). Such
quantities live on a ratio scale and are anchored at a physically meaningful zero;
negative values are typically meaningless.
Absolute quantities stand in contrast to:
Affine points (e.g., \(20\ \mathrm{°C}\), \(100\ \mathrm{m}\ \mathrm{AMSL}\)) — values
measured relative to an arbitrary or conventional origin.
Deltas (e.g., \(10\ \mathrm{K}\), \(–5\ \mathrm{kg}\)) — differences between two values.
Arithmetic on absolute quantities behaves like ordinary algebra: addition, subtraction,
and scaling are well-defined and map naturally to physical reasoning. This article
proposes making absolute quantities the default abstraction in mp-units V3,
reflecting how scientists express equations in practice.
Note: Revised on May 12, 2026 for clarity, accuracy, and completeness.
All quantities and units libraries need to be unit-safe. Most of the libraries
on the market do this correctly. Some of them are also dimension-safe, which
adds another level of protection for their users.
mp-units is probably the only library on the market that additionally is
quantity-safe. This gives a new quality and possibilities. I've described the
major idea behind it, implementation details, and benefits to the users in the
series of posts about the International System of Quantities.
However, this is only the beginning. We've always planned more and worked on the
extensions in our free time. In this post, I will describe:
What a quantity character is?
The importance of using proper representation types for the quantities.
The power of providing character-specific operations for the quantities.
Discuss implementation challenges and possible solutions.
In the previous articles, we introduced the International System of Quantities,
described how we can model and implement it in a programming language, and
presented the issues of software that does not use such abstraction to
implement a units library.
Some of the issues raised in
Part 2 of our series were
addressed in Part 3 already. This article will
present how our ISQ model elegantly addresses the remaining problems.
Up until now, we have introduced the International System of Quantities and
described how we can model its main aspects. This article will present how to
implement those models in a programming language, and we will point out some of
the first issues that stand in our way.
The physical units libraries on the market typically only focus on modeling one
or more systems of units. However, as we have learned, this is not the only
system kind to model. Another, and maybe even more important, is a system of
quantities. The most important example here is the International System of
Quantities (ISQ) defined by ISO/IEC 80000.
This article continues our series about the International System of Quantities.
This time, we will learn about the main ideas behind the ISQ and describe how
it can be modelled in a programming language.