C++ Logo

std-proposals

Advanced search

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

From: Charles R Hogg <charles.r.hogg_at_[hidden]>
Date: Tue, 18 Jun 2024 14:03:00 -0400
On Tue, Jun 18, 2024 at 1:25 PM Tiago Freire <tmiguelf_at_[hidden]> wrote:

> 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.
>

"Analogous" doesn't mean "identical". Quantity point is "analogous" to
chrono's time point, in that (a) it is an affine space type, with all of
the same restrictions on mathematical operations, and (b) the logical
result of subtracting two quantity point (time point) instances is a
quantity (duration). That's the extent of the point I was making.

I also think the need (or lack thereof) for a reference point is orthogonal
to the question of how we should represent these concepts in a software
library. This is an interesting rabbit hole, and I'm tempted to digress,
but I think we'll be better served by my staying on topic.

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.
>

If we do that, there are certain specific wrong things that the user would
be unable to do. But it would also prevent users from doing certain other
*right* things.

I think making it impossible to instantiate a quantity of type "degree
Celsius" is a non-starter, for the simple reason that there are such things
as quantities of degrees Celsius, and it would be nice to let users model
them.

But you're right about the point of agreement: we must avoid interfaces
that silently produce incorrect results when used in a natural way. I just
don't think that cutting off a subset of legitimate use cases is the way to
get there.

Cheers,
Chip


>
> *From:* Std-Proposals <std-proposals-bounces_at_[hidden]> *On Behalf
> Of *Charles R Hogg via Std-Proposals
> *Sent:* Tuesday, June 18, 2024 18:50
> *To:* std-proposals_at_[hidden]
> *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]> wrote:
>
> On Tue, 18 Jun 2024 at 18:38, Mateusz Pusz via Std-Proposals
> <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]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
>

Received on 2024-06-18 18:03:35