C++ Logo

std-proposals

Advanced search

Re: [std-proposals] On the standardization of mp-units P3045R1

From: Tiago Freire <tmiguelf_at_[hidden]>
Date: Tue, 18 Jun 2024 17:25:22 +0000
Hi Charles,
Thanks for your message.

> Currently, both Au and mp-units have hit on the same solution: to provide two abstractions, "quantity" and "quantity point". The chrono library has analogous abstractions, in "duration" and "time point", so there's precedent for this approach.

I disagree with the statement that quantity_point is analogous to time_point currently in the standard.
time_point currently in the standard represents a uniquely identifiable point in time in the history of the universe, it represents something that it is intrinsically immeasurable, for practical purpose it has an internal representation based on an offset to an agreed upon reference that we call an epoch. Had we lost track that today is June 18, there would be no instrument capable of telling you what day it is today.
This is not so true with temperatures, volumes, mass, etc…
With time_point you always need a reference epoch (this is minimal to even make sense) and any internal unit is optional, with quantity_point epoch is very much not required but a unit definition is.

But regardless we agree that silently doing the wrong thing is bad, and that we should fix it.
Can we start by making impossible to instantiate a quantity of type “degree celcius”?
If we do that then a user would be unable to do the wrong thing. The compiler will stop them and complain and force the user to have to figure out what is the right thing.
I would still disagree that quantity_point is the right thing, but at least not doing the obviously wrong thing it is a step in the right direction.


From: Std-Proposals <std-proposals-bounces_at_[hidden].org> On Behalf Of Charles R Hogg via Std-Proposals
Sent: Tuesday, June 18, 2024 18:50
To: std-proposals_at_[hidden]socpp.org
Cc: Charles R Hogg <charles.r.hogg_at_[hidden]>
Subject: Re: [std-proposals] On the standardization of mp-units P3045R1

Hi! I joined the mailing list so that I could join in with this discussion. Unfortunately, I have no idea how to reply to a message that was already sent before I got my membership. So this reply is going to be attached to the wrong message in the thread --- sorry about that!

For context: I'm the author of the Au units library, and a co-author on the paper P3045 under discussion.

Tiago, thank you for providing a concrete example of a usability trap in the library! Having a very specific example to work from will help us move forward. Let's dig in and analyze this.

The core problem (as others have stated) is that there are two different concepts that people might mean when they refer to "temperature". They might mean "absolute" temperature ("what temperature is it?"), or they might mean a temperature difference. It's critically important to know which the user means, because they behave very differently! And we need to support both --- this is simply a complication that we have inherited from the underlying real-world subject matter.

Currently, both Au and mp-units have hit on the same solution: to provide two abstractions, "quantity" and "quantity point". The chrono library has analogous abstractions, in "duration" and "time point", so there's precedent for this approach.

For units libraries, experience shows that "quantity" is almost always what users want, as it supports the mathematical operations of quantity calculus. Temperatures, though, are very different: in practice, we often want "quantity point" (maybe even most of the time!).

I think the bar to meet here is that any code that users will naturally tend to write should not silently produce incorrect results. How to do that here? We could say "make quantity point the default for temperature", but I think a better approach is "avoid having a default for temperature". Here's how Au does this: users can write `celsius_qty(20)` to get a quantity of 20 degrees Celsius, or `celsius_pt` to get a quantity point representing a temperature of 20 degrees Celsius. If users write `celsius(20)`, this is defined, but is marked as `[[deprecated]]` with an error message that directs them to `celsius_qty` and `celsius_pt`, making them aware of the problem, and telling them what solutions are available. See source code: https://github.com/aurora-opensource/au/blob/221d8f41c41419bbdb585fb4cdea1217b8011fd1/au/units/celsius.hh#L37-L42

I think the idea of adding a "permanently deprecated" member to the standard library, purely so that users can get a useful error message if they try to use it, would be a very hard sell, and I'm not proposing it. But I definitely think we need to avoid code that silently produces grossly incorrect answers when used in the natural way. Maybe others can think of a more palatable way to make users aware of the difficulty if they naively try to do the wrong thing? Or maybe it's enough to simply omit the "unadorned" names for temperatures.

By the way: as to the specific code example provided, the error is clearly in the `28.0 * deg_C` expression. As others have pointed out, the multiplicative syntax necessarily only works for quantity, never for quantity point. Au also has "unit symbol" constructs that behave similarly to the example. The way we handle it is to, again, omit the unadorned name. Our unit symbol for degrees Celsius is `deg_C_qty`, putting its nature front and center, and (I hope) suggesting to the end user that they should understand why this symbol looks different from all the others.

On Tue, Jun 18, 2024 at 11:43 AM Ville Voutilainen via Std-Proposals <std-proposals_at_[hidden]<mailto:std-proposals_at_[hidden]>> wrote:
On Tue, 18 Jun 2024 at 18:38, Mateusz Pusz via Std-Proposals
<std-proposals_at_[hidden]<mailto:std-proposals_at_[hidden]>> wrote:
>
> Multiply syntax will always create a quantity. So if I write:
>
> auto q = 4 * deg_C;
>
> I will end up with a delta temperature equal to 4 K.
>
> quantity q = 4 * deg_C; // the same thing as above
>
> If I try:
>
> quantity_point qp = 4 * deg_C;
>
> I will get a compile-time error as a quantity_point is not implicitly constructible from the quantity.
>
> To create a quantity_point, I have to do one of the following:
>
> quantity_point qp1 = zeroth_degree_Celsius + 4 * deg_C;
> quantity_point qp2(4 * deg_C, zeroth_degree_Celsius);
> quantity_point qp3(4 * deg_C); // proper point origin provided by default
>
> All of the above will create a temperature point with a value equal to 277.15 K.

..and chrono allows creating objects of such types with a literal,
whereas this library doesn't?
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]<mailto:Std-Proposals_at_[hidden]>
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2024-06-18 17:25:28