mpusz / mp-units

The quantities and units library for C++
https://mpusz.github.io/mp-units/
MIT License
1.07k stars 85 forks source link

Implement expression templates for units magnitudes #505

Closed mpusz closed 1 week ago

mpusz commented 11 months ago

Right now, magnitudes expand in the user-facing types, which makes them verbose and hard to understand. We could incorporate the same generic approach that we use for other entities as well. Those could either be resolved to prime numbers lazily or be expanded to prime numbers in an invisible base class that will be used for all the arithmetics?

With this, we could get decent types and all the features of the current design. For example instead of quantity<reference<fuel_consumption{}, scaled_unit<magnitude<power_v<2, -2>{}, power_v<5, -2>{}>{}, derived_unit<non_si::litre, per<si::kilo_<si::metre{}>>>>{}>{}, double>> we could get quantity<reference<fuel_consumption{}, scaled_unit<magnitude<1, per<100>>{}, derived_unit<non_si::litre, per<si::kilo_<si::metre{}>>>>{}>{}, double>>.

Also, common units could work fine as we could try to find the GCD for an equation (like std::ratio does).

chiphogg commented 11 months ago

Weighing in for posterity as the original implementer of vector space magnitudes:

I like the idea of using some kind of expression template for the user-facing types that show up in compiler errors. Overall, it seems like a similar strategy to the opaque types we use for units, and which work really well. I think this is worth pursuing.

One possible alternative to expression templates would be for the type to be templated on a string, which is the label for the magnitude. (We don't have magnitude labels yet, but we'll get them someday.) IIRC, we tried this a little bit earlier, but found that the representation in the compiler error was really bad: not only was it character-for-character, but I think the characters were also represented by their numeric ASCII codes (!). If we could get a commitment from all of the compilers to print the type as a string (e.g., magnitude<"5280">) in compiler errors, then this might be better than expression templates, because we wouldn't be limited in terms of what integers we could display. I think expression templates seem like a safer bet overall, though.

mpusz commented 1 week ago

We decided to not go this way. Providing good and readable expression templates for magnitudes is far from being easy and complicates the design too much with not much benefit. To limit the scope of the issue we decided to add support for a common_unit. With this, the raw magnitude type will leak to the user only from the units like l/100km.