Introducing Absolute Quantities¶
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 have a well-defined origin; 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 October 31 2025 for clarity, accuracy, and completeness.
Background¶
Affine Space Recap¶
Until now, mp-units modeled two fundamental abstractions:
- Points – represented by
quantity_pointin V2 - Deltas – represented by
quantity
Info
More information on this subject can be found in the Affine Space chapter.
This design works but is sometimes awkward: users often misuse quantity_point to
represent absolute magnitudes (e.g., total mass), losing arithmetic and printability.
Conversely, using deltas everywhere hides physical intent and allows nonsensical operations.
The new absolute quantity abstraction aims to bridge that gap.
Quantity abstractions in physics¶
Below is a summary table comparing the three main quantity abstractions:
| Feature | Point | Absolute | Delta |
|---|---|---|---|
| Physical Model | Interval Scale | Ratio Scale | Difference |
| Example | \(20\ \mathrm{°C}\), \(100\ \mathrm{m}\ \mathrm{AMSL}\) | \(293.15\ \mathrm{K}\), \(100\ \mathrm{kg}\) | \(10\ \mathrm{K}\), \(-5\ \mathrm{kg}\) |
| Absolute Zero? | No (Arbitrary Zero) | Yes (True Zero) | N/A |
| Allows Negative? | Yes (\(-10\ \mathrm{°C}\)) | No (Opt-in) | Yes (\(-10\ \mathrm{m}\)) |
| A + A | Error (\(20\ \mathrm{°C} + 10\ \mathrm{°C}\)) | Absolute (\(10\ \mathrm{kg} + 5\ \mathrm{kg}\)) | Delta |
| A - A | Delta (\(30\ \mathrm{°C} - 10\ \mathrm{°C}\)) | Delta (\(50\ \mathrm{kg} - 5\ \mathrm{kg}\)) | Delta |
| scalar * A | Error (\(2 \times 20\ \mathrm{°C}\)) | Absolute (\(2 \times 10\ \mathrm{kg}\)) | Delta |
| A / A | Error | scalar (\(10\ \mathrm{kg} / 5\ \mathrm{kg}\)) | scalar |
| API | quantity<point<...>> |
quantity<...> |
quantity<delta<...>> |
This table summarizes the key differences in semantics, API, and physical meaning for each abstraction. Use it as a quick reference when deciding which concept to use in your code.
Motivation¶
This section explains the driving reasons for introducing absolute quantities. It highlights the practical pain points, limitations, and sources of confusion in the current model, motivating the need for a new abstraction.
Current Pain Points¶
- Limited arithmetic for points – Points can’t be multiplied, divided, or accumulated.
This often forces the users to convert the quantity point to a delta with either
qp.quantity_from_zero()orqp.quantity_from(some_origin)member functions, which is at least cumbersome. - No text output for points – A point's textual representation depends on its origin, which is often implicit or user-defined. As of today, we do not have the means to provide a text symbol for the point origin. Moreover, points may contain both an absolute and a relative origin at the same time, which makes it harder to determine which origin to use for printing. Also, the same point may be represented in many ways (different deltas from various origins). Should such a point have the same or a different textual output for each representation?
- Error-prone simplifications – Developers frequently replace points with deltas for convenience, losing safety and physical clarity.
Example¶
Mass Balance in Drying Process
A food technologist is drying several samples of a specific product to estimate its change in moisture content (on a wet basis) during the drying process.
quantity<percent> moisture_content_change(quantity<kg> water_lost, // delta
quantity<kg> total) // absolute
{
gsl_Expects(is_gt_zero(total));
return water_lost / total;
}
quantity<kg> initial[] = { 2.34 * kg, 1.93 * kg, 2.43 * kg };
quantity<kg> dried[] = { 1.89 * kg, 1.52 * kg, 1.92 * kg };
quantity total_initial = std::reduce(std::cbegin(initial), std::cend(initial));
quantity total_dried = std::reduce(std::cbegin(dried), std::cend(dried));
std::cout << "Initial product mass: " << total_initial << "\n";
std::cout << "Dried product mass: " << total_dried << "\n";
std::cout << "Moisture content change: " << moisture_content_change(total_initial - total_dried, total_initial) << "\n";
quantity<percent> moisture_content_change(quantity<kg> water_lost,
quantity_point<kg> total)
{
gsl_Expects(is_gt_zero(total));
return water_lost / total.quantity_from_zero();
}
quantity_point<kg> initial[] = { point<kg>(2.34), point<kg>(1.93), point<kg>(2.43) };
quantity_point<kg> dried[] = { point<kg>(1.89), point<kg>(1.52), point<kg>(1.92) };
auto point_plus = [](QuantityPoint auto a, QuantityPoint auto b){ return a + b.quantity_from_zero(); };
quantity_point total_initial = std::reduce(std::cbegin(initial), std::cend(initial), point<kg>(0.), point_plus);
quantity_point total_dried = std::reduce(std::cbegin(dried), std::cend(dried), point<kg>(0.), point_plus);
std::cout << "Initial product mass: " << total_initial.quantity_from_zero() << "\n";
std::cout << "Dried product mass: " << total_dried.quantity_from_zero() << "\n";
std::cout << "Moisture content change: " << moisture_content_change(total_initial - total_dried, total_initial) << "\n";
In the above example:
water_lostshould be a delta (difference in mass),totalshould conceptually be non-negative absolute amount of mass, yet the type system doesn’t enforce it.
Semantics¶
This section details the semantics of absolute quantities, their relationship to other abstractions, and how they interact in code and mathematics. It clarifies the rules, conversions, and algebraic properties that underpin the new model.
Position of Absolute Quantities Among Abstractions¶
| Feature | Point | Absolute | Delta |
|---|---|---|---|
| Interpolation | ✓ | ✓ | ✓ |
| Multiplication / Division | ✗ | ✓ | ✓ |
| Addition | ✗ | ✓ | ✓ |
| Subtraction | ✓ | ✓ | ✓ |
| May be non‑negative | ✓ | ✓ | ✗ |
| Relative to origin | Explicit | Implicit global 0 | ✗ |
| Can use offset units | ✓ | ✗ | ✓ |
| Convertible to offset units | Via offset | ✗ | No offset |
| Text output | ✗ | ✓ | ✓ |
Absolute quantities sit logically between points and deltas: they behave like deltas algebraically, yet conceptually reference a true zero. This design simplifies arithmetic, improves printing, and preserves physical meaning.
As we can see above, absolute quantities have only two limitations, and both are connected to the use of offset units. They can't use those because they must remain absolute instead of being measured relative to some custom origin.
Simplified API in V3¶
As I mentioned in my previous post,
we are seriously considering removing the quantity_point class template and replacing it
with a quantity_spec point wrapper. For example, quantity_point<isq::altitude[m]> will
become quantity<point<isq::altitude[m]>>.
I initially planned quantity<isq::mass> to be the same as quantity<delta<isq::mass>>,
but it turns out that deltas probably should not be the default. It is consistent with how
we write physical expressions on paper, right? The delta symbol (∆) is always "verbose"
in physical equations. It would be nice for the C++ code to do the same. So, starting with
mp-units V3, deltas will always need to be explicit.
And this brings us to absolute quantities. As we stated in the previous chapter, they could be considered:
- deltas against nothing, and
- points from a well-established zero.
This leads us to the observation that they are the perfect default we are looking for. If we take any physics books, such quantities are the ones that we see in most of the physical equations. This is why we will not need any specifier to denote them in mp-units V3.
Here are some simple examples:
quantity q1 = 20 * kg; // absolute quantity (measured from true zero)
quantity q2 = delta<kg>(20); // delta quantity (difference)
quantity q3 = point<kg>(20); // point quantity (relative to an origin)
The above will produce the following types:
static_assert(std::is_same_v<decltype(q1), quantity<kg>>);
static_assert(std::is_same_v<decltype(q2), quantity<delta<kg>>>);
static_assert(std::is_same_v<decltype(q3), quantity<point<kg>>>);
This mirrors the way physicists write equations: absolute values by default, with explicit Δ when needed.
Alignment with scientific practice¶
The proposed abstractions mirror the way quantities are treated in physics and engineering textbooks:
- Absolute quantities (e.g., mass, energy, length) are always measured from a natural zero and are mostly non-negative.
- Points (e.g., position, temperature on a relative scale) are always defined relative to an origin.
- Deltas (differences) are the result of subtracting two points or two absolutes.
This correspondence ensures that code written with mp-units is not only type-safe, but also directly maps to the equations and reasoning found in scientific literature. This makes code easier to review, verify, and maintain.
Conversions Between Abstractions¶
As absolute quantities share properties of both deltas and points with implicit origins, they should be explicitly convertible to those:
or
The opposite is not always true:
- not every delta will be a positive amount against nothing,
- not every point on the scale will be positive (e.g., altitudes).
This is why it is better only to expose named functions to convert points and deltas to absolute quantities:
quantity<kg> q3 = q1.absolute(); // may fail the pre-condition check if negative
quantity<kg> q4 = q2.absolute(); // may fail the pre-condition check if negative
It is important to note that conversions between absolute quantities and points should be available only when there is no point origin specified for a point (an implicit point origin is being used).
If the user provided an explicit origin, then such a quantity can only be used as a delta:
inline constexpr struct nhn_sea_level final : absolute_point_origin<isq::altitude> {} nhn_sea_level;
quantity<m> alt1 = 42 * m;
quantity<point<m>> alt2(alt1); // OK
// quantity<point<m>, nhn_sea_level> alt3(alt1); // Compile-time error
quantity<point<m>, nhn_sea_level> alt4 = nhn_sea_level + alt1.delta();
If the user used an offset unit, then a conversion should work fine as long as the point origin of the offset unit is defined in terms of the implicit point origin:
quantity<K> temp1 = 300 * K;
quantity<point<K>> temp2(temp1); // OK
quantity<point<C>> temp3(temp1); // OK
To summarize:
| From \ To | Point | Absolute | Delta |
|---|---|---|---|
| Point | Identity | .absolute() |
point - point → delta |
| Absolute | Explicit or .point() |
Identity | Explicit or .delta() |
| Delta | origin + delta → point | .absolute() |
Identity |
Arithmetic Semantics¶
Affine space arithmetic is well-defined and commonly used in physics and engineering. With the introduction of absolute quantities, it is important to clarify the meaning of arithmetic operations involving points, absolutes, and deltas.
Addition¶
Adding two absolute quantities (e.g., \(10\ \mathrm{kg} + 5\ \mathrm{kg}\)) produces another absolute quantity. This is simply the sum of two non-negative amounts, both measured from the true zero of the physical property.
Adding a delta to an absolute quantity (e.g., \(10\ \mathrm{kg} + (-2\ \mathrm{kg})\))
yields a (potentially negative) delta. If you need an absolute quantity as a result,
you must explicitly convert the delta to an absolute quantity (i.e., using .absolute()),
which will check the non-negativity precondition at runtime and may fail if the value
is negative. This approach ensures that negative results are always intentional and
checked, increasing code safety.
Adding an absolute quantity or delta to a point yields a point shifted by the given amount.
Here is the summary of all the addition operations:
| Lhs \ Rhs | Point | Absolute | Delta |
|---|---|---|---|
| Point | Point | Point | |
| Absolute | Point | Absolute | Delta |
| Delta | Point | Delta | Delta |
Info
Here are some numerical examples that present the available operations and their results:
Subtraction¶
Subtraction in the context of physical quantities is best understood as finding the difference between two amounts.
Subtracting two absolute quantities (e.g., \(50\ \mathrm{kg} - 5\ \mathrm{kg}\)) yields a delta (difference), which may be negative or positive. This is consistent with the mathematical and physical meaning of subtraction.
If an absolute result is needed (e.g., remaining mass), it should be obtained via an explicit conversion:
This rule prevents invalid negative absolutes while remaining explicit when needed.
Subtracting a delta from an absolute quantity (e.g., \(10\ \mathrm{kg} - 2\ \mathrm{kg}\))
yields a delta. If you need an absolute quantity as a result, you must explicitly convert
the delta to an absolute quantity (i.e., using .absolute()), which will check the
non-negativity precondition at runtime and may fail if the value is negative. This
approach ensures that negative results are always intentional and checked, increasing
code safety.
Subtracting an absolute quantity from a point yields a point, and subtracting a point from an absolute quantity is not meaningful.
Here is a summary of all of the subtraction operations
| Lhs \ Rhs | Point | Absolute | Delta |
|---|---|---|---|
| Point | Delta | Point | Point |
| Absolute | Delta | Delta | |
| Delta | Delta | Delta |
Info
Here are some numerical examples that present the available operations and their results:
quantity abs = isq::height(42 * m);
quantity pt = point<isq::altitude[m]>(10);
quantity d = delta<isq::height[m]>(2);
quantity res1 = pt - abs; // Point
// quantity res2 = abs - pt; // Compile-time error
quantity res3 = abs - pt.absolute(); // Delta or quantity_difference
quantity res4 = abs - d; // Delta
quantity res5 = d - abs; // Delta
Interpolation¶
Interpolation of absolute quantities (e.g., finding a value between \(a\) and \(b\)) is well-defined and results in another absolute quantity. This is commonly used in physics and engineering for averaging, blending, or estimating values between two known points.
Non-negativity¶
Non-negativity of absolute quantities is meant to be an opt-in feature in the quantity
specification. For example, we can pass a non_negative tag type in quantity definition:
With that, we will be able to mark any quantity as non-negative and this property will be inherited by the subquantities in the quantity hierarchy tree of the same kind.
We could also derive non-negativity for derived quantities based on their equations. A non-negative flag could be set only if all of the components in the equations are marked as non-negative. However, we will not be able to account for a negative scalar possibly used in an equation. This is why it is probably better to assume that ad-hoc derived quantities do not inherit this property. If this result is assigned to a typed/named quantity, then the non-negativity will be checked then (if set).
Interesting Quantity Types¶
Time¶
Let's look closer at the quantity of time. There is no way to measure its absolute value as we don't even know where (when?) the time axis starts... Only time points and time deltas (durations) make sense.
However it seems that the ISQ thought this through already. It does not define a quantity of time at all. It only provides duration defined as:
ISO 80000-3:2019
name: duration
symbol: \(t\)
Definition: measure of the time difference between two events
Remarks: Duration is often just called time. Time is one of the seven base quantities in the International System of Quantities, ISQ (see ISO 80000-1). Duration is a measure of a time interval.
As long as absolute quantity<isq::time[s]> may seem off, quantity<isq::duration[s]>
is OK as an absolute quantity. Durations typically should be non-negative as well.
If we need a negative duration then quantity<delta<isq::duration[s]>> makes sense.
isq::time should be reserved for affine space point only
(e.g., quantity<point<isq::time>[s]>). You can find more about this in my
Bringing Quantity-Safety To The Next Level
blog article.
The above does not mean that we should always use typed quantities for time. We can still use simple quantities and the library will reason about them correctly:
quantity<s>or42 * s-> absolute durationquantity<delta<s>>ordelta<s>(-3)-> delta durationquantity<point<s>>orpoint<s>(94573457438583)-> time point
Length¶
A somewhat similar case might be the length quantity, as there is no one well-established
zero origin that serves as a reference for all length measurements. However, asking the
users always to provide a delta specifier for length would probably be overkill.
Everyone can imagine what no length/radius/height means. Also, most of us are okay
with each object having its own length measurement origin.
Note
In the context of absolute quantities, quantity<m> always represents a size (such
as the length, width, or height of an object), not a position in space.
Positions are modeled using the point<m> abstraction, which always refers to
a location relative to a defined origin.
This distinction ensures that code using absolute quantities for size cannot be
confused with code representing positions. For example, quantity<m> is used
for the length of a rod, not its position in space.
Electric Current¶
Electric current is the only ISQ base quantity that has a well defined zero point (no current flow in the wire), but its values can be both positive and negative depending on the direction the current flows.
We could be tempted to model electric current as the 1-dimensional vector quantity, but probably it is not the best idea. It is officially defined as a signed scalar quantity.
Absolute electric current values should be available, but should not perform a non-negative precondition check on construction and assignment.
Temperature¶
As we pointed out before, it will be possible to form absolute quantities of temperature, but only when the unit is (potentially prefixed) Kelvin. For offset units like degree Celsius, it will not be possible.
If the user has a temperature point in Celsius and wants to treat it as an absolute quantity and pass it to some quantity equation, then such point first needs to be converted to use Kelvin as its unit and then we need to create an absolute quantity from it:
quantity temp = point<deg_C>(21);
quantity kinetic_energy = 3 / 2 * si::boltzmann_constant * temp.in(K).absolute();
Which Quantity Abstraction Should I Use?¶
The decision tree below provides guidance on choosing the appropriate quantity abstraction for a specific use case. Start with the first question and follow the path based on your answers:
flowchart TD
ask_point{{Adding two quantities of this type makes sense?}}
ask_point -- No --> Point[Point]
ask_point -- Yes --> ask_delta{{Possibly negative difference/distance between two quantities?}}
ask_delta -- Yes --> Delta[Delta]
ask_delta -- No --> Absolute[Absolute]
%% Styling
classDef pointStyle fill:#ff9999,stroke:#cc0000,stroke-width:2px,color:#000
classDef deltaStyle fill:#99ff99,stroke:#00cc00,stroke-width:2px,color:#000
classDef absoluteStyle fill:#99ccff,stroke:#0066cc,stroke-width:2px,color:#000
classDef questionStyle fill:#fff2cc,stroke:#d6b656,stroke-width:2px,color:#000
class Point pointStyle
class Delta deltaStyle
class Absolute absoluteStyle
class ask_point,ask_delta questionStyle
Bug Prevention and Safety Benefits¶
The new model eliminates a class of subtle bugs that arise from conflating positions, sizes, and differences. For example:
- No accidental addition of positions
- the type system prevents adding two
point<m>objects, which is physically meaningless
- the type system prevents adding two
- No silent sign errors
- subtracting two absolute quantities always yields a delta, so negative results are explicit and must be handled intentionally
- No misuse of offset units
- absolute quantities cannot be constructed with offset units (like Celsius), preventing incorrect temperature calculations
- Compile‑time enforcement
- most mistakes caught before runtime
Revised Example¶
Let's revisit our initial example. Here is what it can look like with the absolute quantities usage:
Mass Balance in Drying Process
A food technologist is drying several samples of a specific product to estimate its change in moisture content (on a wet basis) during the drying process.
quantity<delta<percent>> // (1)!
moisture_content_change(quantity<delta<kg>> water_lost, // (2)!
quantity<kg> total) // (3)!
{
// gsl_Expects(is_gt_zero(total)); (4)
return water_lost / total;
}
quantity<kg> initial[] = { 2.34 * kg, 1.93 * kg, 2.43 * kg }; // (5)!
quantity<kg> dried[] = { 1.89 * kg, 1.52 * kg, 1.92 * kg };
quantity total_initial = std::reduce(std::cbegin(initial), std::cend(initial)); // (6)!
quantity total_dried = std::reduce(std::cbegin(dried), std::cend(dried));
std::cout << "Initial product mass: " << total_initial << "\n"; // (7)!
std::cout << "Dried product mass: " << total_dried << "\n";
std::cout << "Moisture content change: " << moisture_content_change(total_initial - total_dried, total_initial) << "\n"; // (8)!
- Theoretically a negative result is possible if the product gained water in the process of drying.
- Explicit delta.
- Absolute quantity.
- No longer needed as absolute quantities of mass will have a precondition of being non-negative.
- Simple initialization of absolute quantities.
- Arithmetic works.
- Test output works.
- Type safe!
This version is concise, physically sound, and type‑safe. Function arguments can't be reordered and non‑negativity guarantees remove the need for manual runtime checks.
Migration and Backward Compatibility¶
Although the theory in the chapters above may seem intimidating, users will not be significantly affected by the changes in mp-units V3.
As we can see, the new code above does not differ much from our previously unsafe but
favored version. The only difference is that we spell delta explicitly now, and that we
can safely assume that absolute values of mass are non-negative. The rest looks and feels
the same, but the new solution is safer and more expressive.
The biggest migration challenge is related to the results of subtraction on two
quantities, points, or deltas. From now on, they will result in a different type
(i.e., quantity<delta<...>>) which is not implicitly convertible to an absolute
quantity.
quantity<km / h> avg_speed(quantity<km> distance, quantity<h> duration)
{
return distance / duration;
}
quantity_point<km> odo1 = ...;
quantity_point<s> ts1 = ...;
quantity_point<km> odo2 = ...;
quantity_point<s> ts2 = ...;
quantity res = avg_speed((odo2 - odo1).absolute(), (ts2 - ts1).absolute()); // OK
In case of an invalid order of subtraction arguments, the precondition check will fail at runtime only for the conversion to absolutes case. This increases the safety of our code.
Another migration challenge may be related to the usage of negative values. All of the
ISQ base quantities besides electric current could be defined to be non-negative
for absolute quantities. This means that if a user is dealing with a negative
delta today, such code will fail the precondition check in the absolute quantity
constructor. To fix that, the user will need to use explicit delta specifiers or
construction helpers in such cases:
quantity<m> d1 = -2 * m; // Precondition check failure at runtime
quantity<delta<m>> d2(-2 * m); // Precondition check failure at runtime
quantity d3 = delta<m>(-2); // OK
Regarding temperature support, in the Semantics chapter, we said that a new abstraction will not work for offset units. However, it was also the case in mp-units V2. If we check The Affine Space chapter we will find a note that:
Quote
The multiply syntax support is disabled for units that provide a point origin in
their definition (i.e., units of temperature like K, deg_C, and deg_F).
We always found those confusing and required our users to be explicit about the intent
with point and delta construction helpers. So nothing changes here from the coding
point of view. From the design point of view, we replace some strange corner case design
constraint with a properly named abstraction that models that behavior.
Actually, V3 will improve temperature support significantly. Thanks to the new abstraction, we will be able to multiply and divide absolute temperatures with other quantities, but only if the temperature is measured in Kelvin. Also, the multiply syntax will work to construct such absolute quantities (e.g., \(300 \times \mathrm{K}\)).
Last, but not least, the quantity_point<...> class template will be replaced with
quantity<point<...>> syntax.
Key Migration Rules¶
| V2 Pattern | V3 Equivalent | Notes |
|---|---|---|
quantity<kg> |
quantity<kg> |
Before delta and now absolute |
quantity<kg> m = m1 - m2; |
quantity<kg> m = (m1 - m2).absolute(); |
Explicit if you want abs |
quantity<kg> dm = m1 - m2; |
quantity<delta<kg>> dm = m1 - m2; |
Explicit deltas when negative value possible |
quantity_point<kg> p = ...; |
quantity<point<kg>> p = ... |
Use point<kg> wrapper |
quantity<kg> d = p - point<kg>(42); |
quantity<delta<kg>> d = p - point<kg>(42); |
Deltas must be explicit |
Most user code will continue to compile after adding explicit delta or .absolute()
conversions where needed.
Rationale¶
Here we discuss the rationale behind the proposed changes, including the design philosophy, alignment with scientific practice, and the benefits for standardization and future extensibility.
Non-negativity in Physical Equations vs API Design¶
In most physical equations, the quantities we work with are expected to be non-negative amounts. For example, mass, energy, distance, and duration are all inherently non-negative in physical reality. While the mathematical abstraction of a delta (difference) allows for negative values, in practice, negative deltas are rare or even unphysical in many domains.
Consider the case of speed:
Quote
Speed is defined as the ratio of a change in length (distance traveled) to a change in time (duration):
\(speed = \frac{\Delta length}{\Delta time}\)
While the formula uses deltas, in almost all practical scenarios, both \(\Delta length\) and \(\Delta time\) are non-negative. A negative duration, for example, is not physically meaningful and would indicate a logic error in most applications.
Prefer absolute quantities for non-negative deltas¶
This has important implications for API design. If a function like avg_speed accepts
deltas as arguments, users might inadvertently pass negative values, leading to
nonsensical results or subtle bugs:
// Problematic: allows negative duration
quantity<m/s> avg_speed(quantity<delta<m>> distance, quantity<delta<s>> duration)
{
return distance / duration;
}
Instead, it is safer and more physically correct to require absolute quantities for
such parameters, leveraging the fact that ISQ provides distance and duration as
non-negative quantities:
This approach ensures that only non-negative values can be passed, preventing negative durations or distances from entering your calculations. This reduces the risk of bugs, makes your code more robust, and better reflects the intent of most physical equations.
New opportunities¶
The new syntax allows us to model quantities that were impossible to express before without some workarounds.
For example, we can now correctly calculate Carnot engine efficiency with any of the following:
quantity temp_cold = 300. * K;
quantity temp_hot = 500. * K;
quantity carnot_eff_1 = 1. - temp_cold / temp_hot;
quantity carnot_eff_2 = (temp_hot - temp_cold) / temp_hot;
In the above code, we can easily create absolute or delta values of temperatures and perform arithmetic on them. Previously, we had to create deltas from both points artificially with:
quantity temp_cold = point<K>(300.);
quantity temp_hot = point<K>(500.);
quantity carnot_eff_1 = 1. - temp_cold.quantity_from_zero() / temp_hot.quantity_from_zero();
quantity carnot_eff_2 = (temp_hot - temp_cold) / temp_hot.quantity_from_zero();
It worked, but was far from being physically pure and pretty.
Design Philosophy and Standardization¶
Absolute quantities make physical semantics explicit while simplifying common use cases. They expose existing conceptual complexity rather than adding new layers. The design is:
- Consistent with ISQ – mirrors the distinction between displacement, position, and difference.
- Predictable – clear subtraction and conversion rules.
- Scalable – a single
quantityclass handles all variants via wrappers. - Safe – non‑negativity and offset‑unit rules prevent misuse.
- Extensible – additional quantity abstractions may be added in the future by simply introducing a new wrapper (e.g., anchored quantities).
For standardization, this model brings three tangible benefits:
- Closer alignment with physical reasoning used by scientists and engineers.
- Improved readability and verification in generic C++ code.
- Zero runtime overhead — all checks are compile‑time or lightweight preconditions.
Conclusion¶
Adding absolute quantities elevates mp-units from a dimensional analysis tool to a true physical reasoning framework. The proposal clarifies semantics, improves safety, and aligns code directly with equations found in textbooks. This is not extra complexity—it's the formalization of the real structure of physical space in C++ types.
We plan to deliver this as part of mp-units V3 and welcome community and WG21 feedback.