Article
Safer C++ Firmware: Strong Types, Units, and Validation Boundaries
A September 30, 2026 workshop announcement provides a starting point for examining strong types in firmware. Explore which unit and argument mistakes types can prevent, and where runtime validation remains necessary.
Share
Koharu's reading tip
Matching units do not necessarily mean matching roles. Watch what the type system protects, and where that protection ends when values become plain numbers.

When reading firmware configuration, it is natural to ask what a number represents and which unit it uses. “Building Safer Firmware in Modern C++,” scheduled for September 30, 2026, puts encoding that meaning in types at the center of its workshop.
Variable names may distinguish values for a reader, but a function accepting identical integer types cannot necessarily distinguish them for the compiler. More precise types also do not make incoming sensor readings valid.
The useful question is where compile-time prevention ends and runtime validation begins. C++ design guidance and official mp-units documentation provide supporting examples for exploring the design goal behind the announcement.
Encoding units and roles lets types reject swapped arguments
Consider an illustrative function accepting a sampling period and a voltage threshold. If both arguments are integers, swapping them still satisfies the signature. Distinct types without implicit conversions between them can reject that call. C++ Core Guidelines I.4 recommends expressing interface meaning through precise types.
The physical quantities library mp-units extends this approach to units and calculations. It rejects adding length to time and handles compatible unit conversions, keeping units in calculations instead of relying on names and handwritten scaling factors. Its safety documentation explains these distinctions.
Units alone cannot distinguish every role. A sampling period and a timeout are both durations; accepting the same duration type still permits a swap. Role-specific types can add the missing distinction.
The official exercise on quantities of the same kind explores this through height, width, and turning radius. The mistakes an interface should reject determine how much meaning its types need.
Correct units do not eliminate runtime bounds checks
A value typed as voltage can still exceed the range a device accepts. Identifying the quantity and deciding whether its value is acceptable are separate requirements. Settings whose values and constraints can be evaluated during a build can undergo static validation; measurements and messages arriving afterward require validation at runtime.
The mp-units bounds validation exercise processes external weather data, checks limits, and handles violations. It illustrates concentrating validation where typed values enter the system.
Those checks also need to survive production builds. The guide to always-on constraint enforcement explains that default bounds checks using MP_UNITS_EXPECTS may be compiled away in release builds, and describes combining checks with error policies. The behavior after rejecting an input needs deliberate design too.
Check units and representation when handing numbers to legacy APIs
Existing driver APIs may still require integers or floating-point numbers. In mp-units, numerical_value_in(Unit) provides a conversion boundary that explicitly names the requested unit. The legacy interface guide documents this approach.
Once extracted, however, the result is an ordinary number. The guide explicitly notes that it cannot prevent subsequent truncation when a returned double is passed to an int parameter. Matching units does not guarantee that the receiving representation preserves the value.
A practical starting point is to keep calculations typed and reconcile units, representation, and acceptable range immediately before calling a driver. Limiting the places where values become raw numbers makes the end of type protection easier to inspect.
Start with a small interface on the target firmware compiler
The mp-units compiler support table lists C++20 as the minimum language requirement and gives compiler-specific conditions. At research time, it excludes Clang 19. For an embedded project, test the chosen library version with the actual toolchain rather than relying only on the language-standard setting.
The announced workshop offers an opportunity to study this design. Mateusz Pusz is scheduled to teach the live online Packt session on September 30, 2026, from 15:00 to 19:30 CEST. The announcement identifies unit mixups, argument swaps, and out-of-range configuration as errors to catch early.
For practical adoption, start with an interface containing numbers with different meanings. Try type-based prevention there, validate external inputs, and make conversions explicit at legacy boundaries. Separating compiler-enforced conditions from runtime decisions is how the meaning of a value can survive its journey through firmware.
Source
- Title: Hands-on workshop on September 30: Building Safer Firmware in Modern C++ -- Mateusz Pusz
- URL: https://isocpp.org//blog/2026/09/hands-on-workshop-on-september-30-building-safer-firmware-in-modern-cpp-mat
Share
Related Articles
These articles share nearby categories or tags, so you can keep reading along the same thread.




