Why is chrono so shortsighted?

574 views
Skip to first unread message

carel.c...@gmail.com

unread,
May 26, 2017, 8:08:16 AM5/26/17
to ISO C++ Standard - Future Proposals
Hi All,

Don't get me wrong, the chrono library added in C++11 is absolutely brilliant. 

BUT: Time is not the only unit that many C++ developers use. Many developers use other units like distance, frequency, etc. 

The way chrono is implemented does not give developers the option to extend the powerful conversion support implemented in the library. 

What I am referring to is the whole duration structure and the associated templates and functions, that could be commonly used between different units. 

Some suggestions that I found was to define one's own types using duration as a base, but this solves the conversion issue, but type safety is then a problem.
For example:
#define std::chrono::duration<int32_t> meters;
The issue is since it is not type safe, one can assign seconds to meters, which is a problem.  

I have played around with this idea and created a very similar implementation of a base quantity type but using a opaque or phantom type to ensure type safety (based on a CppCon talk I saw on this). 

Currently duration is defined as follow:
   template<typename _Rep, typename _Period = ratio<1>> struct duration;
   typedef duration<int64_t> seconds;

So what I have come up with is a base structure defined as follow:
    template<typename _Rep, typename _Period, typename _Quantity> struct quantity_base;

Which is then used as follow, to redefine the time types (for example and tests): 
    struct unit_time;

    template<typename _Rep, typename _Period = std::ratio<1>>
      using duration = quantity_base<_Rep, _Period, unit_time>;

    typedef duration<int64_t, std::milli> milliseconds;
    typedef duration<int64_t> seconds;
    typedef duration<int64_t, std::ratio<60>> minutes;

    template<typename _ToQuantity, typename _Rep, typename _Period>
    constexpr typename __check_unit<unit_time, _ToQuantity>::type
    duration_cast(const duration<_Rep, _Period>& __d)
    {
      return quantity_base_cast<_ToQuantity>(__d);
    }

The rest of the templates are almost exactly the same as from chrono, but it takes into account the _Quantity template argument to ensure one can not mix different quantities;

Using this base implementation one can then add new types as follow, for example distance:

      struct unit_distance;

    template<typename _Rep, typename _Period = std::ratio<1>>
    using distance = quantity_base<_Rep, _Period, unit_distance>;

    template<typename _ToQuantity, typename _Rep, typename _Period>
    constexpr typename __check_unit<unit_distance, _ToQuantity>::type
    distance_cast(const distance<_Rep, _Period>& __d)
    {
      return quantity_base_cast<_ToQuantity>(__d);
    }

    typedef distance<int64_t, std::milli> millimeters;
    typedef distance<int64_t> meters;
    typedef distance<int64_t, std::kilo> kilometers;

This implementation is not nearly as advanced as some other libraries, notably the "Unit Conversion and Dimensional Analysis Library" from Nic Holthaus[1]

Is this something that could possibly be incorporated or is planned for future updates?
Not really suggesting to use my implementation, but more the general idea to add support for more units and/or the ability for users to add other units, without having to code all the detail but reuse the "magic" already there in the chrono library.

[1] Unit Conversion and Dimensional Analysis Library

Thiago Macieira

unread,
May 26, 2017, 11:42:24 AM5/26/17
to std-pr...@isocpp.org
On Friday, 26 May 2017 05:08:16 PDT carel.c...@gmail.com wrote:
> Is this something that could possibly be incorporated or is planned for
> future updates?

It's possible, as long as duration doesn't actually change its kind (it's a
struct today, it shall remain a struct).

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center

carel.c...@gmail.com

unread,
May 30, 2017, 2:58:48 PM5/30/17
to ISO C++ Standard - Future Proposals


It's possible, as long as duration doesn't actually change its kind (it's a
struct today, it shall remain a struct).


There are currenlty a few other more complete and complex unit libraries available, like the one mentioned in the original post and Boost.Units. Does it make sense to try and change the way that chrono works to allow for better reuse, or should the effort rather go into getting such a complex/complete library into the standard, if at all possible?


Thiago Macieira

unread,
May 30, 2017, 3:14:05 PM5/30/17
to std-pr...@isocpp.org
On Tuesday, 30 May 2017 11:58:48 PDT carel.c...@gmail.com wrote:
> > It's possible, as long as duration doesn't actually change its kind (it's
> > a
> > struct today, it shall remain a struct).
>
> There are currenlty a few other more complete and complex unit libraries
> available, like the one mentioned in the original post and Boost.Units
> <http://www.boost.org/doc/libs/1_64_0/doc/html/boost_units.html>. Does it
> make sense to try and change the way that chrono works to allow for better
> reuse, or should the effort rather go into getting such a complex/complete
> library into the standard, if at all possible?

Your objective was to add more units, so I think you should investigate the
solution that includes more units before you investigate the implementation
details (what needs to change in chrono).

Tony V E

unread,
May 30, 2017, 3:21:20 PM5/30/17
to ISO C++ Standard - Future Proposals
I hear talk of work on a std::units library. 

I think a group of people worked on it at Boostcon / C++Now

Sent from my BlackBerry portable Babbage Device
Sent: Tuesday, May 30, 2017 2:58 PM
To: ISO C++ Standard - Future Proposals
Subject: Re: [std-proposals] Why is chrono so shortsighted?



It's possible, as long as duration doesn't actually change its kind (it's a
struct today, it shall remain a struct).


There are currenlty a few other more complete and complex unit libraries available, like the one mentioned in the original post and Boost.Units. Does it make sense to try and change the way that chrono works to allow for better reuse, or should the effort rather go into getting such a complex/complete library into the standard, if at all possible?


--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/bb0629a6-b3f4-4c54-b4b9-f53e91b565ba%40isocpp.org.

carel.c...@gmail.com

unread,
May 30, 2017, 3:48:51 PM5/30/17
to ISO C++ Standard - Future Proposals

I hear talk of work on a std::units library. 

I think a group of people worked on it at Boostcon / C++Now

I would be very interested to hear more if someone has some information on this, from a quick google search I could not find anything. 

carel.c...@gmail.com

unread,
May 30, 2017, 4:07:14 PM5/30/17
to ISO C++ Standard - Future Proposals

Your objective was to add more units, so I think you should investigate the
solution that includes more units before you investigate the implementation
details (what needs to change in chrono).

In my usage of C++ I need only a very small subset of units but with the auto conversion between different scales in the same unit.

So yes initially I was only hoping to reuse what was already present in chrono.

But this is perhaps a bigger topic, what type of unit support would one like to see in the C++ standard in future:
a) A small(ish) library that contains some base units (time being one) but with the ability for users to extend the units and add those needed without too much manual code.
b) Or a more full fledged library that understands most base/common units and can convert between them when used in dimensional analysis with mathematical operations?

Boost.Unit and the Unit Conversion and Dimensional Analysis Library are examples of b. What I was leaning towards was more a.
Both of the above are quite powerful, but in my view have some limitations that are addressed by the chrono library, such as:
- Chrono will not implicitly convert to a unit with a different scale if precision will be lost (ns -> s) but will convert implicitly if precision will not be lost (s -> ns).
- The underlying storage unit in chrono is an integer type which removes the issue of comparing for equality.

Vicente J. Botet Escriba

unread,
May 30, 2017, 6:18:14 PM5/30/17
to std-pr...@isocpp.org, carel.c...@gmail.com
I believe that a) will already be quite useful and lighter than b). I've a strong_counter class that is quite close to a dimension-less or uni-dimension quantity. Note that I want also to count the number of orange on a bag.

The problem is that these simple quantities will not play well forcedly with multidimensional quantities in b). If we had a design that allows to have simple dimension-less or uni-dimension quantities that work with multidimensional quantities as well, then this could done step by step. So a) should should show a way to b) with backward compatibility.

If we don't want to changes chrono::duration ABI we could always define implicit conversions from/to quantity<time_dimension>.
In the worst case we could have implicit constructors from the quantities defined in a) and the ones defined in b).

I believe there is a lot of people that will profit from a).

Vicente

Arthur O'Dwyer

unread,
May 30, 2017, 6:55:31 PM5/30/17
to ISO C++ Standard - Future Proposals, carel.c...@gmail.com
I can confirm that yes, one group of participants at Library-in-a-Week was exploring the Boost.Units space. I don't know who all was in the group, but their most visible member was Peter Sommerlad. He gave a lightning talk one morning explaining some terminology.

The thing I remember most about that talk is that the "units" are the easy part; one of the many hard parts is "dimension". For example, if you're flying a plane, you actually don't really care about the difference between "meters" and "miles" as long as the conversion factors are handled properly; but you really care about the difference between "miles of distance" and "miles of altitude".

In fact, you probably REALLY care about the difference between "miles above sea level" and "miles above ground level"... and yet, at the same time, you need to be able to do arithmetic computations involving both quantities together.

(By "care about", I mean "implicit conversions between the two would be horrific.")

Anyway, maybe you can ask Peter. His email is easy to find online. That lightning talk from C++Now might even be online somewhere, for all I know.

–Arthur

Patrice Roy

unread,
Jun 1, 2017, 11:08:57 AM6/1/17
to std-pr...@isocpp.org, vincent....@usherbrooke.ca
I'll be meeting a guy named Vincent Ducharme (cc'ed) next week. He's been maintaining his own units library, which has been used by others for some scientific work already and has nice usability / performance characteristics. He contacted me following a visit from Peter (Somerlad) on his github repo. I'll try to see what making his work meet the chrono idioms would require; if it's reasonable work and if it looks promising, I'll push for him to write a proposal.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

John McFarlane

unread,
Jun 1, 2017, 9:31:40 PM6/1/17
to std-pr...@isocpp.org, vincent....@usherbrooke.ca
I sat in on a few of the sessions at C++Now. A lot of time was spent exploring the API design space which is remarkably broad. Here is one prototype that Steven Watanabe shared: https://github.com/swatanabe/cppnow17-units/

The obviously forum to discuss a units library would be the numeric group but there is no easily-accessible reflector for that group. I'm working on a fixed-point numeric type and I see a lot in common between fixed-point and dimensional types. I aim to conduct some experiments to see if this can be exploited somehow.

Regarding chrono::duration, I see no reason to assume that a units library needs to extend or incorporate it. Time is a special case in computing. So adding a separate time type as part of a units library is worth considering if it leads to a better solution.

To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

Howard Hinnant

unread,
Jun 1, 2017, 9:51:49 PM6/1/17
to std-pr...@isocpp.org
<Disclaimer> I am only remotely familiar with units libraries. </Disclaimer>

I’m not positive, but I believe units libraries deal mainly with units from an engineering perspective, which means the library deals only with (e.g.) length, and not position. The chrono library goes to a great deal of trouble to keep “length” (duration) and “position” (time_point) separate types. The advantage is in restricting the algebra of “positions”. "Position 1 + Position 2” is non-sensical. But "Position 1 - Position 2” makes perfect sense, and is not a position, but a length.

It would be interesting if this algebra could be incorporated into a units library. If it already is, color me impressed.

Howard

signature.asc

Chris Hallock

unread,
Jun 2, 2017, 12:12:01 AM6/2/17
to ISO C++ Standard - Future Proposals

The Boost.Units library lets the user declare a "point, not vector" style unit with boost::units::absolute.

Nicol Bolas

unread,
Jun 2, 2017, 1:10:34 AM6/2/17
to ISO C++ Standard - Future Proposals

That's interesting.

Here's another unusual case. Consider 4x4 transformation matrices. A transformation matrix takes positions/vectors in one space and transforms them into another. So for unit analysis, you want to be able to tag positions/vectors with a particular space. When you try to transform them by a matrix, if they're not in the same space as the input of the matrix, then you get an error. And the result of the transformation is a vector in the output space of the matrix.

This also would need to handle transformation composition. If you have two matrices A and B, you can only compose B with A if the output space of A matches the input space of B. Inverting a matrix swaps the input and output spaces. And so forth.

I don't suppose someone has found a way to resolve something like that.

Martin Moene

unread,
Jun 2, 2017, 1:25:42 AM6/2/17
to std-pr...@isocpp.org

Peter Sommerlad

unread,
Jun 2, 2017, 5:07:15 AM6/2/17
to std-pr...@isocpp.org, vincent....@usherbrooke.ca
Hi 

Sorry for being late on that thread. I am the one who started the Liaw group at C++now this year. More Info and participants are at 
https://wiki.hsr.ch/PeterSommerlad/wiki.cgi?CppNow2017Units

The current plan is to make nic holthaus' library more flexible using Steven watanabes idea on flexible domain analysis. nic's currently limited to 7 SI dimensions plus Angles. 

If you want to learn more email me. Unfortunately I didn't yet have time to work on it. I have about half a dozen proposals in flight that require updates for Toronto. 

Regards
Peter

send from a mobile device.
Prof. Peter Sommerlad
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

Martin Moene

unread,
Jun 2, 2017, 6:49:28 AM6/2/17
to std-pr...@isocpp.org, Peter Sommerlad, vincent....@usherbrooke.ca
On 02-Jun-17 11:07, Peter Sommerlad wrote:
> Sorry for being late on that thread. I am the one who started the Liaw group
> at C++now this year. More Info and participants are at
> https://wiki.hsr.ch/PeterSommerlad/wiki.cgi?CppNow2017Units
>
Yet another library:

https://github.com/njoy/DimensionalAnalysis (note license)

Martin

Chris Hallock

unread,
Jun 2, 2017, 5:02:54 PM6/2/17
to ISO C++ Standard - Future Proposals
On Friday, June 2, 2017 at 1:10:34 AM UTC-4, Nicol Bolas wrote:
Here's another unusual case. Consider 4x4 transformation matrices. A transformation matrix takes positions/vectors in one space and transforms them into another. So for unit analysis, you want to be able to tag positions/vectors with a particular space. When you try to transform them by a matrix, if they're not in the same space as the input of the matrix, then you get an error. And the result of the transformation is a vector in the output space of the matrix.

This also would need to handle transformation composition. If you have two matrices A and B, you can only compose B with A if the output space of A matches the input space of B. Inverting a matrix swaps the input and output spaces. And so forth.

I don't suppose someone has found a way to resolve something like that.

I think that if you have a sufficiently flexible linear algebra library (one that can handle user-defined element types and that correctly deduces the element type of A*B as decltype(a*b) instead of just decltype(a) or decltype(b), where a and b are elements of matrices A and B, respectively), you can handle this by having vector and matrix types whose element types are quantity types and by using dimensionless "tag" units to denote specific spaces. For example, let's say you want to transform some vector v, in meters, from space X to space Y (identified by dimensionless units "X" and "Y", respectively) with transformation matrix A. v must initially have units of m*X. The result, A*v, must have units of m*Y. Therefore, A must have units of Y/X – cancel out the X tag (input), tack on the Y tag (output).
Reply all
Reply to author
Forward
0 new messages