Document: P3045R7
Authors: Mateusz Pusz, Dominik Berner, Johel Ernesto Guerrero Peña, Charles Hogg, Nicolas Holthaus, Roth Michaels, Vincent Reverdy
Date: 2026-02-22
Audience: LEWG
Target: C++29
Seven revisions in, the quantities and units library continues its march toward C++29. This is the standardization path for the mp-units design: compile-time-safe physical quantities with dimensions, units, quantity kinds, affine spaces, and formatted text output, all grounded in the International System of Quantities (ISQ).
Croydon gave it its first LEWG review after years of incubation in SG6, SG16, and LEWGI. Evening tutorial session followed by directional polls - all passed with no SA or A votes. The paper is 354KB and covers everything from the Mars Climate Orbiter to temperature point arithmetic. Targeting C++29 with field trials requested.
Every time someone asks "why do we need a units library in the standard" I say three words: Mars Climate Orbiter. $327 million spacecraft lost because someone mixed up pound-seconds and newton-seconds. A type system that catches
metres + secondsat compile time is not academic luxury. It is basic engineering safety.Section 8.1 calls it "the proliferation of
double." Every physics codebase I've worked on has functions that take 4-5 doubles and the only way to know which is velocity vs acceleration vs time is the parameter name. And parameter names aren't checked by the compiler.354 kilobytes. Seven revisions. Dimensions, units, quantity kinds, quantity references, affine spaces, point origins, formatting, ISQ alignment. This is a genuinely ambitious library. My concern is whether it's trying to do too much for C++29. Could we ship a core subset (dimensions + units + basic quantities) and add kinds/affine spaces in C++32?
Quantity kinds without affine spaces means you can't model temperature correctly. Celsius and Kelvin are point origins, not just unit conversions. 20°C + 20°C is not 40°C - it's a type error. The affine space model catches this. If you ship without it, you teach a generation of developers the wrong mental model and then break their code when you add it later.
Fair point on temperature. I withdraw the suggestion. Ship it whole or don't ship it.
The design goal hierarchy is exactly right: safety first, performance second, ergonomics third. A units library that isn't zero-overhead is dead on arrival for scientific computing. A zero-overhead units library that isn't type-safe is pointless. mp-units has demonstrated both in production. The question was always whether it could clear the committee process.
Section 5.1 on interaction with
std::chronois the elephant in the room.std::chrono::durationis already a quantity-of-time. The new library needs to interoperate seamlessly or we'll have two incompatible time representations in the standard. The paper acknowledges this and proposes interconversion, but it's going to need careful LWG review.Howard designed
std::chronowith exactly this kind of dimensional analysis in mind. The ratio-based approach was always meant to generalize. This library is the generalization he anticipated. Interop should be natural, not forced.Was in the Croydon evening session. Pusz gave a thorough tutorial - the room was full. The directional polls afterward were the strongest consensus I've seen on a new library facility in years. No SA, no A, on any of the core direction pillars. People want this.
Strong direction polls are nice but the paper is explicitly asking for field trials before standardization. That's the right call for a library this large. Let production users find the sharp edges before we bake it into the IS.
I write flight control software. Every function signature in my codebase is
double, double, double, double. Altitude in feet or meters? Airspeed in knots or m/s? Angle in degrees or radians? You check the comments. Comments lie. This library would eliminate an entire category of bugs we spend real money finding.The quantity kinds system is where the design gets complex. "Width" and "height" are both lengths but are different kinds. You can't add width to height. This is correct from a dimensional analysis standpoint but it's going to surprise a lot of people who think
quantity<si::metre>is just "a number with a unit."The question is whether the complexity pays for itself in practice or whether most users will just use
quantity<si::metre>and ignore kinds entirely.In mp-units you CAN just use
quantity<si::metre>and ignore kinds. Kinds are opt-in. The default is "length is length." If you want the extra safety of distinguishing width from height, you opt in by defining a kind. Progressive disclosure.Seven authors. Multiple libraries unified. Section 6 has individual bio paragraphs for each. Holthaus wrote
nholthaus/units. Pusz wrote mp-units. Hogg works on Aurora (self-driving). Reverdy does astrophysics. This is the rare WG21 paper where the authors collectively represent the actual user base.This library is going to be the showcase for C++20 concepts. Generic interfaces constrained by
QuantityOf<isq::speed>instead ofdouble. Return types that encode dimensional information. This is what concepts were designed for - not justrequires std::integral<T>, but rich domain constraints.The zero-overhead claim is backed by mp-units benchmarks showing identical codegen to raw doubles once the optimizer runs. The type safety is entirely a compile-time artifact. At runtime,
quantity<si::metre>(42.0)is just42.0.The formatted text output support is underrated.
std::format("{}", 120 * km / h)producing"120 km/h"with correct SI unit symbols, correctly handling derived units, and supporting both portable ASCII and UTF-8 output. SG16 reviewed the text handling. This is how a modern C++ library should do formatting.Honest question: is this useful outside science/engineering? I write game engines. My units are "pixels", "frames", and "whatever the art director decided this week." None of which are in the ISQ.
Section 9.5: the library is extensible. You can define custom dimensions, units, and quantity types. "Pixels per frame" could be a first-class quantity in your codebase. The ISQ units are the built-in set; user-defined units sit on the same footing.
F# has had units of measure since 2005. Compile-time dimensional analysis, zero runtime overhead, built into the type system. C++ is twenty years late to this party. Better late than never.
A concepts-heavy library with deeply nested template types. The error messages when you mess up a unit conversion are going to be legendary. I hope the paper addresses diagnostics.
In practice the error messages are better than you'd expect. The concepts constrain at the right level so you get "cannot convert quantity of length to quantity of time" not "no matching function for call to
operator+with 47 candidates." mp-units has worked on this specifically.354KB of paper. What's the header weight going to be? If including the units library adds 5 seconds to my compile, I'll stick with strong typedefs and comments, thanks.
C++29 is the right target. This library needs bake time. Field trials, production feedback, compiler diagnostics improvements. Rush it and we get another
std::regex. Take our time and we get anotherstd::chrono.Boost.Units exists and has been shipping since 2008. It works. The new design is better - concepts, constexpr, modern C++ - but let's not pretend this problem hasn't been solved in practice.
By the time this ships, my physics simulation will have been rewritten in Rust twice. But I'm still excited.