196th ROOT Parallelism, Performance and Programming Model Meeting
PPP 09.04.2026
mp units library and ROOT
Mateusz: We have met in Croydon last week finalising C++26 and first meeting of C++29. During this meeting we agreed on the entire scope for the proposal of the mp-units. What I'm telling today will probably be part of the C++29 standard.
Mateusz: Call to action: in order to improve we need feedback. Potentially we are in time to influence the shape of the library and change the standard proposal
[Vincenzo]: How does mp-units help with CODATA?
Mateusz: version selection
[Vincenzo]: wouldn't this make it more complicated for the standard to accept the proposal?
Mateusz: We won't provide HEP-specific features for standardization. mp-units provides all 6 levels of safety as described in slide 15. This puts it at a better level then other units libraries. For the HEP-specific features, these won't be in the standard but mp-units can be used as a framework.
[Giacomo/Vincenzo]: What is the square bracket operator in slide 19, syntactically?
Mateusz: These are type instances and there are free non-member functions that allow using the square bracket operator to "overload" and dispatch orthogonal types to combine functionalities. Example proper_time[ns] where both proper_time and ns are actual instances of types.
[Giacomo]: Why did you choose this syntax?
Mateusz: I use the convention of writing quantity units with square brackets as is customary in schools/university classes.
[Giacomo]: Any idea about the impact on compile-time?
Mateusz: It always depends. It will be slower, but is not as slow as you could be worried about. Usage of std::format, std::view, std::ranges is much slower than mp-units according to my measurements. The most expensive things to include are actually things you may not be interested in. For example the si.h header instantiates all standard units, that's costly on its own. You could not include this header and only instantiate the units you need in your own code. The mp-units library is built with C++ modules in mind, which in the long term should be there but not yet. When modules will be widely available, the cost should be even lower.
[Giacomo]: Have you considered splitting the headers? Having one conveniency header sounds good on paper, but all users may have to pay the cost downstream.
Mateusz: Removing this header in particular gave me about 15% faster compile time, but I was only compiling a simple program that would just include that header or not.
[Giacomo]: My main concern is with larger projects where the extra compile cost may accumulate. I don't know if there are large projects using this already?
Mateusz: Yes, and we haven't received speed complaints from anyone yet.
Mateusz: An interesting test would be to just include one or some of the header files in mp-units and then check the build time of your project. If you do that, let me know as I am interested.
[Vincenzo]: If my function signature specifies exactly type and its quantity, e.g. space[mm], can I pass a raw double and that will be implicitly converted to space[mm]?
Mateusz: That's not allowed, instantiation of function arguments only works via either multiplying the double with the unit type (e.g. 25*mm) or via the explicit constructor with two arguments, e.g. SpaceUnit(25, mm). Even the explicit constructor with just one argument wouldn't work in general because of cases with structs and data members with aggregate initializations.
[Dev]: What if you don't have a unit defined? For example the return value of the function has a unit that does not exist yet in the standard?
Mateusz: You can compose units. You can write something made up e.g. constexpr auto hep_unit = kg /m3 * K and then use it afterwards in your functions.
[Philippe]: You mentioned Walter's work. He tried back then to include SI units in the standard. Your library is being considered for the standard, so that's a significant change. I can see that some of the improvements in the C++ standard are helping a lot in your case. Can you single out some of the C++ standard features that make your effort succesfull?
Mateusz: Walter's approach was great 30 years ago. In the meanwhile we learned how to write proper abstractions and we got new tools that made us more efficient. In Walter's library everything was stored in meters by default and then you had to pay the cost for every conversion. Compared to other libraries (see slide 48), they are great but were written before. None of them provide support across all levels of safety. I was approached by many engineers by many domains saying if I only care about the units my library wouldn't be adopted. Walter's library was about units and runtime units alone. Compile-time units + all the new abstractions allowed us to achieve more than ever before. You will find more details about this in my recent report after the meeting with the C++ standard group in Croydon.
[Lukas]: Incluing the si.h header is a good test to see how the compile time increases. I wonder once all this machinery is used in a larger project how much that will impact.
Mateusz: Maybe use the hep header, not the si.h one as that has even more things you don't need. About the machinery, I think that won't matter much as most things instantiated will be reused by the compiler. I'm doing measurements but not for such large projects as yours. So far I haven't got any complaints about performance of compile-time.
[Lukas]: how would you recommend to include the library where it can't be included? Maybe with wrappers? Let's assume you have a project with third-party dependencies. In those dependencies you can't include those quantities, but you can in your own. Would you define wrappers to go in and outside of the third-party dependencies?
Mateusz: Yes I would write wrappers. You can already start doing it now, write wrappers for the ROOT APIs. Leave current APIs for legacy users and new APIs for new users.
[Vincenzo]: Question from Oliver Lantwin in the chat: about writing mp-units types to ROOT datasets. What's needed?
[Vincenzo]: There's no technical blocker, in the end mp-units data is just doubles, but hypothetically if the user wanted to also store the type (e.g. whether the double is in cm or mm), we would need to store this information on disk
[Philippe]: Our files are self-describing, so we can reconstruct the entire structure of the classes in memory
[Giacomo]: The ROOT serialization layer would need to deal with being consistent about the representation on disk of the in-memory types. Key part being making sure that the unit you pass when serializing is the same the user requests when deserializing.
[Philippe]: Just to confirm, in memory the layout of the quantity is strictly just a double, right?
[Philippe]: So yes it would be straightforward to store.
Useful links
https://mpusz.github.io/mp-units/latest/blog/2026/03/28/report-from-the-croydon-2026-iso-c-committee-meeting/
https://indico.cern.ch/event/1642384/contributions/6907824/attachments/3226673/5751411/Bringing%20Safety%20to%20HEP.pdf
https://mpusz.github.io/mp-units/latest/reference/systems_reference/systems/hep/