[chrono] Interoperability with ICL and common concepts

Hi Vicente and Boost Chronoists, thank you for implementing Boost.Chrono! It's a very fine piece of software :) Currently I'm checking out the usage of chrono types with icl::intervals and interval containers. Obviously, using intervals of chrono::time_points or chrono::durations can be an important use case. Also ICL already works well with other date and time data types from boost data_time, so chrono's interoperability should be at least as easy. A problem here is, that Icl, while working instantly with built in data types (e.g. int, short, double or even int*), for other numeric types (e.g. boost::rational) or types "based on integral types" (e.g. data_time::ptime) I needed to provide adapter code. I think it'd be ideal, if boost libraries interoperated with each other just out of the box, of course. To achive this, we have to find a common understanding of those concepts, that make a seamless interoperability work. I think, this is important work to be done, because it widens the view from one's own library perspective to a broader horizon of generic interplay. The problem: There is a minimal set of requirements that Icl expects for the domain types of intervals and interval containers (1) A zero element, more precisely an identity element w.r.t. the type's composition operation, which usually is +. An assumption that works well for all built in types and many STL-types is, that we get this element by the default constructor T(). (2) A strict weak ordering < (3) For all discrete types and for continuous numeric types: Operators ++, -- (Only pre-variants needed e.g. ++x) (3.1) For discrete types ++/-- increments/decrements by a *least step* (3.2) For continuous numeric types ++/-- increments/decrements by a *unit step*. Most of the functionality of Icl works if requirements (1) through (3) are met. In addition, there are some functions that require a distance type, but only for more specific types, namely for numeric types that use varying interpretations of the origin (zero), like epoch based date and time and pointer-addresses. BTW, do we already have a name for this type of concept? origin_based_equidistant_scalar origin_based_equidifferential_scalar because they are based to an arbitrary origin, but have comparable differences or distances. Or shorter equidistant_scalar equidifferential_scalar because if we emphasize, that by "comparable differences or distances", it is implied that the origin is choosable. May favorite is "equidistant_scalar". This concept reminds me of "Levels of measurement" http://en.wikipedia.org/wiki/Level_of_measurement (4) For such equidistant scalar types D the ICL assumes, that the type of the difference values of D is D::difference_type. To summarize, for a domain type Dom, Icl expects Dom(), <, ++, -- and if dom is a equidistant scalar type we expect an associated type Dom::difference_type to be defined. Now boost::chrono::duration (D1*) Has a default ctor that leaves the type undefined. (D2) Has <, Ok. (D3) Has ++, --, Ok. boost::chrono::time_point (T1) Has a default ctor that implements the semantics assumed by the ICL, Ok. (T2) Has <, Ok. (T3*) Does not have ++, --. (T4*) Does not have difference_type So I end up with 3 of my requirements not met (D1, T3, T4) D1: Default ctor for chrono::duration leaves objects undefined. I assume this is due to efficiency considerations, nevertheless unfavorable from the view point of my library. For all built in types and most of the STL there has been something like an intuitive maybe unconscious may be conscious agreement to assign the identity element w.r.t. the fundamental composing operation of the constructed object's type as the semantics of the default ctor. From an algebraic, generic and interoprability point of view (and IMHO) this is the best choice. This choice has not been taken for chrono::durations, which is a little inconsistent also, because interestingly for its chrono::time_point type the semantic is just the desired one. The possibility of default ctor customization is no remedy, because ICL should ideally be completely "chrono agnostic" and still interoperable. For the same reason duration::zero() is not an option. T3: chrono::time_point does not implement ++ and --. I assume this is because of the specific maths that is designed for chrono::time_points (P) and durations (D) where - : P x P -> D + : P x D -> P + : D x P -> P but + : P x P -> P //verboten But this should not be an argument against ++ and -- because the "least steppable unit" for integral rep types as well as the "unit" for floating point rep types, that is processed by ++ and -- is the same for time_points and durations. T4: Finally, difference_type as the associated type for time_point is not defined. IMO, it should be, because from a concept point of view, chrono::time_point falls in the same equidistant scalar concept that other types are in (e.g. T*, random_access_iterator<T>) and those associate a difference_type. These are the main problems of Icl/Chrono interoperability. There are a few minor ones as well. Let's discuss these first. I hope we can arrive at a solution, where Icl can be chrono agnostic and vica versa and still everything works well together. Based on that, we could fix similar issues for other libs like data_time. Cheers, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

Joachim Faulhaber wrote:
The possibility of default ctor customization is no remedy, because ICL should ideally be completely "chrono agnostic" and still interoperable. For the same reason duration::zero() is not an option.
Why can't ICL have a customization point for the identity value that defaults to T()? Then chrono can customize that (assuming there is a suitable value to use). _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

2011/3/15 Stewart, Robert <Robert.Stewart@sig.com>:
Joachim Faulhaber wrote:
The possibility of default ctor customization is no remedy, because ICL should ideally be completely "chrono agnostic" and still interoperable. For the same reason duration::zero() is not an option.
Why can't ICL have a customization point for the identity value that defaults to T()? Then chrono can customize that (assuming there is a suitable value to use).
Hi Robert :) Hmm ... good simple question. So this implies a solution like this: //=== in or under boost/chrono/chrono.hpp ================== namespace boost{namespace icl { template<class Type>struct identity_element; template<class Rep, class Period> struct identity_element<boost::chrono::duration<Rep,Period> > { typedef boost::chrono::duration<Rep,Period> duration_type; typedef identity_element type; static duration_type value() { return duration_type::zero(); } }; }} //========================================================== right? Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

Joachim Faulhaber wrote:
2011/3/15 Stewart, Robert <Robert.Stewart@sig.com>:
Why can't ICL have a customization point for the identity value that defaults to T()? Then chrono can customize that (assuming there is a suitable value to use).
Hmm ... good simple question. So this implies a solution like this:
//=== in or under boost/chrono/chrono.hpp ==================
namespace boost{namespace icl { template<class Type>struct identity_element;
template<class Rep, class Period> struct identity_element<boost::chrono::duration<Rep,Period> > { typedef boost::chrono::duration<Rep,Period> duration_type; typedef identity_element type;
static duration_type value() { return duration_type::zero(); } }; }}
//==========================================================
right?
That looks pretty good, except perhaps instead of declaring identity_element in the chrono header, it should include <boost/icl/identity_element.hpp> and just specialize for chrono::duration. That leaves ICL as the sole owner of the primary specialization. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

2011/3/15 Stewart, Robert <Robert.Stewart@sig.com>:
Joachim Faulhaber wrote:
2011/3/15 Stewart, Robert <Robert.Stewart@sig.com>:
Why can't ICL have a customization point for the identity value that defaults to T()? Then chrono can customize that (assuming there is a suitable value to use).
Hmm ... good simple question. So this implies a solution like this:
//=== in or under boost/chrono/chrono.hpp ==================
namespace boost{namespace icl { template<class Type>struct identity_element;
template<class Rep, class Period> struct identity_element<boost::chrono::duration<Rep,Period> > { typedef boost::chrono::duration<Rep,Period> duration_type; typedef identity_element type;
static duration_type value() { return duration_type::zero(); } }; }}
//==========================================================
right?
That looks pretty good, except perhaps instead of declaring identity_element in the chrono header,
hmm, this was my c++ mini satori of the day, because I realized authors of Boost.Chrono can avoid to do
it should include <boost/icl/identity_element.hpp>
just that! Recall, I wanted ICL to be Chrono agnostic and Chrono to be ICL agnostic. Why? Because ICL shall interoperate out of the box with Boost.Onorhc and Chrono with Boost.LCI libraries that will be written in the future.
and just specialize for chrono::duration. That leaves ICL as the sole owner of the primary specialization.
Would there be any negative consequences otherwise? Cheers, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

Joachim Faulhaber wrote:
2011/3/15 Stewart, Robert <Robert.Stewart@sig.com>:
Joachim Faulhaber wrote:
//=== in or under boost/chrono/chrono.hpp ==================
namespace boost{namespace icl { template<class Type>struct identity_element;
template<class Rep, class Period> struct identity_element<boost::chrono::duration<Rep,Period> > { [snip] }; }}
//==========================================================
That looks pretty good, except perhaps instead of declaring identity_element in the chrono header,
hmm, this was my c++ mini satori of the day, because I realized authors of Boost.Chrono can avoid to do
it should include <boost/icl/identity_element.hpp>
just that!
Recall, I wanted ICL to be Chrono agnostic and Chrono to be ICL agnostic.
You make a good point, but I'd expect that the Chrono specialization would be in a special header that only ICL users would include. Thus, non-ICL Chrono users would never see the dependency. It's not agnosticism, of course, but it is insular. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

2011/3/16 Stewart, Robert <Robert.Stewart@sig.com>:
Joachim Faulhaber wrote:
2011/3/15 Stewart, Robert <Robert.Stewart@sig.com>:
Joachim Faulhaber wrote:
//=== in or under boost/chrono/chrono.hpp ==================
namespace boost{namespace icl { template<class Type>struct identity_element;
template<class Rep, class Period> struct identity_element<boost::chrono::duration<Rep,Period> > { [snip] }; }}
//==========================================================
That looks pretty good, except perhaps instead of declaring identity_element in the chrono header,
hmm, this was my c++ mini satori of the day, because I realized authors of Boost.Chrono can avoid to do
it should include <boost/icl/identity_element.hpp>
just that!
Recall, I wanted ICL to be Chrono agnostic and Chrono to be ICL agnostic.
You make a good point, but I'd expect that the Chrono specialization would be in a special header that only ICL users would include.
You know how people are, particularly under time pressure. If things don't work instantly, a high percentage abandons the effort and tries something else. Some of those who don't give up will have difficulties to find the clues for ICL-interoperability and the exact name of that header file in the docs. Why imposing all that hassle on users, if the interoperability, that doesn't need additional includes and no customization points is so straight forward: (1) A default constructor that is initialized with zero (2) An increment/decrement on the least steppable unit (3) A difference_type declaration Very simple, very little effort, great benefit for instant interoperability, not only with ICL but with all generic libraries that depend on this minimal set of fundamental information. Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

Joachim Faulhaber wrote:
(2) An increment/decrement on the least steppable unit (3) A difference_type declaration
Very simple, very little effort, great benefit for instant interoperability, not only with ICL but with all generic libraries that depend on this minimal set of fundamental information.
Joachim, could you create a ticket for (3). I don't think this is too disruptive. For (2), I will rephrase your least steppable unit as follows. The semantics associated to++,-- is to interpret the unit as the duration of the time_point. Given Atime_point tp; tp++ will be equivalent to tp += Atime_point::duration(1); Howard, do you think that there is a chance this semantics could be accepted for TR2? Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/chrono-Interoperability-with-ICL-and-comm... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Mar 16, 2011, at 11:48 AM, Vicente Botet wrote:
Joachim Faulhaber wrote:
(2) An increment/decrement on the least steppable unit (3) A difference_type declaration
Very simple, very little effort, great benefit for instant interoperability, not only with ICL but with all generic libraries that depend on this minimal set of fundamental information.
Joachim,
could you create a ticket for (3). I don't think this is too disruptive.
For (2), I will rephrase your least steppable unit as follows. The semantics associated to++,-- is to interpret the unit as the duration of the time_point.
Given Atime_point tp;
tp++
will be equivalent to
tp += Atime_point::duration(1);
Howard, do you think that there is a chance this semantics could be accepted for TR2?
I think there's a chance. I'm not sure enough to be able to say whether that chance is high or low. The chances would probably improve if boost's use of it did show benefit and did not show any problems. I don't immediately see any problems with this addition. I think it should be specified/implemented as: Returns: time_point(d_++); where d_ is the "// exposition only" member in the specification of time_point. This will ensure that if Rep has any unusual properties associated with operator++(int), it will be picked up via duration::operator++(int) and subsequently time_point::operator++(int). -Howard

2011/3/16 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 16, 2011, at 11:48 AM, Vicente Botet wrote:
Joachim Faulhaber wrote:
(2) An increment/decrement on the least steppable unit (3) A difference_type declaration
Very simple, very little effort, great benefit for instant interoperability, not only with ICL but with all generic libraries that depend on this minimal set of fundamental information.
Joachim,
could you create a ticket for (3). I don't think this is too disruptive.
For (2), I will rephrase your least steppable unit as follows. The semantics associated to++,-- is to interpret the unit as the duration of the time_point.
Given Atime_point tp;
tp++
will be equivalent to
tp += Atime_point::duration(1);
Howard, do you think that there is a chance this semantics could be accepted for TR2?
I think there's a chance. I'm not sure enough to be able to say whether that chance is high or low. The chances would probably improve if boost's use of it did show benefit and did not show any problems.
I have a large test suite for generic intervals and interval containers. Each of the tests can be iterated over mpl::lists of types. Currently those tests work for a great variety of types: All numeric built in types, T*, string, boost::rational date_time dates, times and durations I could instantiate the test suite for a selection of variants of chrono time_points and durations and run them on all trunk test platforms. Also I could write something about adapter code free concept based generic interoperability featuring Boost.Chrono and Boost.ICL ;-) [We don't have a boost authors blog?]
I don't immediately see any problems with this addition.
:) I only need the pre in/decrement variant in ICL ++i, --i. But one would probably add both variants in one go.
I think it should be specified/implemented as:
Returns: time_point(d_++);
where d_ is the "// exposition only" member in the specification of time_point. This will ensure that if Rep has any unusual properties associated with operator++(int), it will be picked up via duration::operator++(int) and subsequently time_point::operator++(int).
I don't understand this. But the aspect that is important for me from the ICL point of view is efficiency here. For discrete domain types operators ++ and -- are called frequently in ICL functions. So they should be fast. IIUC the operation finally is an in/decrement on the rep_ member which *is* fast particularly if Rep is a built in numeric type. Cheers, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

On Mar 16, 2011, at 12:36 PM, Joachim Faulhaber wrote:
I think it should be specified/implemented as:
Returns: time_point(d_++);
where d_ is the "// exposition only" member in the specification of time_point. This will ensure that if Rep has any unusual properties associated with operator++(int), it will be picked up via duration::operator++(int) and subsequently time_point::operator++(int).
I don't understand this. But the aspect that is important for me from the ICL point of view is efficiency here. For discrete domain types operators ++ and -- are called frequently in ICL functions. So they should be fast. IIUC the operation finally is an in/decrement on the rep_ member which *is* fast particularly if Rep is a built in numeric type.
I concur with your analysis. -Howard

Joachim Faulhaber wrote:
2011/3/16 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 16, 2011, at 11:48 AM, Vicente Botet wrote:
Joachim Faulhaber wrote:
(2) An increment/decrement on the least steppable unit (3) A difference_type declaration
Very simple, very little effort, great benefit for instant interoperability, not only with ICL but with all generic libraries that depend on this minimal set of fundamental information.
Joachim,
could you create a ticket for (3). I don't think this is too disruptive.
For (2), I will rephrase your least steppable unit as follows. The semantics associated to++,-- is to interpret the unit as the duration of the time_point.
Given Atime_point tp;
tp++
will be equivalent to
tp += Atime_point::duration(1);
Howard, do you think that there is a chance this semantics could be accepted for TR2?
I think there's a chance. I'm not sure enough to be able to say whether that chance is high or low. The chances would probably improve if boost's use of it did show benefit and did not show any problems.
I have a large test suite for generic intervals and interval containers. Each of the tests can be iterated over mpl::lists of types. Currently those tests work for a great variety of types:
All numeric built in types, T*, string, boost::rational date_time dates, times and durations
I could instantiate the test suite for a selection of variants of chrono time_points and durations and run them on all trunk test platforms. Also I could write something about adapter code free concept based generic interoperability featuring Boost.Chrono and Boost.ICL ;-) [We don't have a boost authors blog?]
I don't immediately see any problems with this addition.
:)
I only need the pre in/decrement variant in ICL ++i, --i. But one would probably add both variants in one go.
I think it should be specified/implemented as:
Returns: time_point(d_++);
where d_ is the "// exposition only" member in the specification of time_point. This will ensure that if Rep has any unusual properties associated with operator++(int), it will be picked up via duration::operator++(int) and subsequently time_point::operator++(int).
I don't understand this. But the aspect that is important for me from the ICL point of view is efficiency here. For discrete domain types operators ++ and -- are called frequently in ICL functions. So they should be fast. IIUC the operation finally is an in/decrement on the rep_ member which *is* fast particularly if Rep is a built in numeric type.
Joachim, please could you create a ticket for that extension feature :) Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/chrono-Interoperability-with-ICL-and-comm... Sent from the Boost - Dev mailing list archive at Nabble.com.

Vicente Botet wrote:
Joachim,
please could you create a ticket for that extension feature :)
Best, Vicente
I have committed the 3 request as for revision 70074. Please do however the ticket. best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/chrono-Interoperability-with-ICL-and-comm... Sent from the Boost - Dev mailing list archive at Nabble.com.

2011/3/17 Vicente Botet <vicente.botet@wanadoo.fr>:
Vicente Botet wrote:
Joachim,
please could you create a ticket for that extension feature :)
Best, Vicente
I have committed the 3 request as for revision 70074.
That's nice to hear :) I will write tests to prove seamless ICL / chrono interoperability once the features are implemented
Please do however the ticket.
done! Best regards, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

Hi Vicente, Howard and Chronoists, 2011/3/16 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 16, 2011, at 11:48 AM, Vicente Botet wrote:
Joachim Faulhaber wrote:
Vicente, thank you for implementing the additions on boost::chrono discussed in this thread
(1) A default constructor on chrono::duration that is initialized with zero. (2) An increment/decrement on the least steppable unit (3) A difference_type declaration
Howard, do you think that there is a chance this semantics could be accepted for TR2?
I think there's a chance. I'm not sure enough to be able to say whether that chance is high or low. The chances would probably improve if boost's use of it did show benefit and did not show any problems.
According to Howard's remarks, I have instantiated a test suite of 16 non trivial test programs using various chrono time points and durations on ICL intervals and interval containers. http://www.boost.org/development/tests/trunk/developer/icl.html Based on those changes, ICL users are now able to use chrono::time_points and durations in ICL intervals and interval containers without the need of any special adaptercode (e.g. a boost/ICL/chrono.hpp). Everything looks perfect now :) Cheers, Joachim P.S.: Sidenote. Although points (1) trough (3) are a good foundation for this chrono icl interoperability, I had to add some introspection code in addition. I'm not perfectly satisfied with that. I feel there is a concept missing here, that should be the basis of interoperability for types like chrono::time_point/durations, date_time::date/time/durations, third_party::date/time/durations and other types resembling the same concept of an equidistant scalar type. -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

2011/3/16 Vicente Botet <vicente.botet@wanadoo.fr>:
Joachim Faulhaber wrote:
(2) An increment/decrement on the least steppable unit (3) A difference_type declaration
Very simple, very little effort, great benefit for instant interoperability, not only with ICL but with all generic libraries that depend on this minimal set of fundamental information.
Joachim,
could you create a ticket for (3). I don't think this is too disruptive.
Yep!

Joachim Faulhaber wrote:
2011/3/16 Stewart, Robert <Robert.Stewart@sig.com>:
Joachim Faulhaber wrote:
Recall, I wanted ICL to be Chrono agnostic and Chrono to be ICL agnostic.
You make a good point, but I'd expect that the Chrono specialization would be in a special header that only ICL users would include.
You know how people are, particularly under time pressure. If things don't work instantly, a high percentage abandons the effort and tries something else. Some of those who don't give up will have difficulties to find the clues for ICL-interoperability and the exact name of that header file in the docs. Why imposing all that hassle on users, if the interoperability, that doesn't need additional includes and no customization points is so straight forward:
(1) A default constructor that is initialized with zero (2) An increment/decrement on the least steppable unit (3) A difference_type declaration
Very simple, very little effort, great benefit for instant interoperability, not only with ICL but with all generic libraries that depend on this minimal set of fundamental information.
I have written half a dozen replies to you arguing various points, but I keep coming back to this: regardless of whether the customization is done as you or I have suggested, the only way to ensure the code is correct is for a library providing such customizations to include a test case that builds some ICL code using that library's customized type(s). Following my suggested approach, the compiler can verify that the template parameter lists agree during phase one template parsing. Following your approach, the compiler cannot verify even that much. However, that's an incomplete test at best, so it's hardly a compelling argument. Given that my approach requires including yet another header, even when the customization is not used (and assuming such a header is included by a library's include-all header), and the need for test code to fully validate the customization, your approach is better. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

2011/3/17 Stewart, Robert <Robert.Stewart@sig.com>:
Joachim Faulhaber wrote:
2011/3/16 Stewart, Robert <Robert.Stewart@sig.com>:
Joachim Faulhaber wrote:
Recall, I wanted ICL to be Chrono agnostic and Chrono to be ICL agnostic.
You make a good point, but I'd expect that the Chrono specialization would be in a special header that only ICL users would include.
You know how people are, particularly under time pressure. If things don't work instantly, a high percentage abandons the effort and tries something else. Some of those who don't give up will have difficulties to find the clues for ICL-interoperability and the exact name of that header file in the docs. Why imposing all that hassle on users, if the interoperability, that doesn't need additional includes and no customization points is so straight forward:
(1) A default constructor that is initialized with zero (2) An increment/decrement on the least steppable unit (3) A difference_type declaration
Very simple, very little effort, great benefit for instant interoperability, not only with ICL but with all generic libraries that depend on this minimal set of fundamental information.
Hi Robert :)
I have written half a dozen replies to you arguing various points,
the conversation we had in this thread was very helpful for me to get clear about various aspects of the problem. So for me the issues are kind of settled and I am happy that Vicente and Hinnant agreed to my proposals :)
but I keep coming back to this: regardless of whether the customization is done as you or I have suggested, the only way to ensure the code is correct is for a library providing such customizations to include a test case that builds some ICL code using that library's customized type(s).
I think the question of correctness goes beyond what is required for interoperability. std::set for instance requires an ordering and assumes by default that data parameter T implements 'operator <' for client code. If client class T does not provide < the author of T can provide adapter code struct MyLess { bool operator()... } If T were from a Boost.Tee library. The author would probably provide 'operator <' to ensure seamless interoperability with std::set. Whether the implementation of 'operator <' is correct is a different story and will probably be ensured by tests for Boost.Tee.
Following my suggested approach, the compiler can verify that the template parameter lists agree during phase one template parsing. Following your approach, the compiler cannot verify even that much. However, that's an incomplete test at best, so it's hardly a compelling argument.
The glue is IMO the understanding of the common concepts used by the generic library and its client code. In the example case of Boost.Tee it is the common understanding of a total or a strict weak ordering. Between ICL and Chrono it's the common understanding of time_points or what I've called equidistant scalar types, which I think is the underlying concept of say time and temperature scales (except for Kelvin). Cheers, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

Joachim Faulhaber wrote:
2011/3/17 Stewart, Robert <Robert.Stewart@sig.com>:
Joachim Faulhaber wrote:
2011/3/16 Stewart, Robert <Robert.Stewart@sig.com>:
Joachim Faulhaber wrote:
Recall, I wanted ICL to be Chrono agnostic and Chrono to be ICL agnostic.
You make a good point, but I'd expect that the Chrono specialization would be in a special header that only ICL users would include.
You know how people are, particularly under time pressure. If things don't work instantly, a high percentage abandons the effort and tries something else. Some of those who don't give up will have difficulties to find the clues for ICL-interoperability and the exact name of that header file in the docs. Why imposing all that hassle on users, if the interoperability, that doesn't need additional includes and no customization points is so straight forward:
(1) A default constructor that is initialized with zero (2) An increment/decrement on the least steppable unit (3) A difference_type declaration
Very simple, very little effort, great benefit for instant interoperability, not only with ICL but with all generic libraries that depend on this minimal set of fundamental information.
Hi Robert :)
I have written half a dozen replies to you arguing various points,
the conversation we had in this thread was very helpful for me to get clear about various aspects of the problem. So for me the issues are kind of settled and I am happy that Vicente and Hinnant agreed to my proposals :)
Hi, I think however that you need to add the indirections as soon or later you will find a user that is unable to change the class she uses and need a configuration point. Between Boost friends I understand that this open configuration is not needed but ... ;-) HTH, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/chrono-Interoperability-with-ICL-and-comm... Sent from the Boost - Dev mailing list archive at Nabble.com.

2011/3/18 Vicente Botet <vicente.botet@wanadoo.fr>:
(1) A default constructor that is initialized with zero (2) An increment/decrement on the least steppable unit (3) A difference_type declaration
I think however that you need to add the indirections as soon or later you will find a user that is unable to change the class she uses and need a configuration point.
Fortunately I already have suitable templates for (1) and (3) and also (2) is already encapsulated in a function template that can easily be changed for the a customization point (a template struct that allows for partial template instantiation). So basically I need to change very little except for extending customization chapter in the docs.
Between Boost friends I understand that this open configuration is not needed
and the kind of "mutual library agnosticism" based on common concepts is a good thing for decoupled interoperable components.
but ... ;-)
This discussion has been a very insightful one for me. Many thanks to you, Hinnant and Robert :) Cheers, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

Joachim Faulhaber wrote:
Hi Vicente and Boost Chronoists,
thank you for implementing Boost.Chrono! It's a very fine piece of software :)
Thanks :)
Currently I'm checking out the usage of chrono types with icl::intervals and interval containers. Obviously, using intervals of chrono::time_points or chrono::durations can be an important use case. Also ICL already works well with other date and time data types from boost data_time, so chrono's interoperability should be at least as easy.
A problem here is, that Icl, while working instantly with built in data types (e.g. int, short, double or even int*), for other numeric types (e.g. boost::rational) or types "based on integral types" (e.g. data_time::ptime) I needed to provide adapter code.
I think it'd be ideal, if boost libraries interoperated with each other just out of the box, of course. To achive this, we have to find a common understanding of those concepts, that make a seamless interoperability work. I think, this is important work to be done, because it widens the view from one's own library perspective to a broader horizon of generic interplay.
Recall that adding an indirection use to solve a lot of problems.
The problem: There is a minimal set of requirements that Icl expects for the domain types of intervals and interval containers (1) A zero element, more precisely an identity element w.r.t. the type's composition operation, which usually is +. An assumption that works well for all built in types and many STL-types is, that we get this element by the default constructor T().
What about creating a customization point identity or zero template struct zero { T value() { return T(); } }; The user or Boost.Chrono could specialize it. template <...> struct zero<duration<...> > { T value() { return duration<...>::zero(); } };
(2) A strict weak ordering < (3) For all discrete types and for continuous numeric types: Operators ++, -- (Only pre-variants needed e.g. ++x) (3.1) For discrete types ++/-- increments/decrements by a *least step* (3.2) For continuous numeric types ++/-- increments/decrements by a *unit step*.
The same can be done for customizations points increase_unit, and decrease_unit.
(4) For such equidistant scalar types D the ICL assumes, that the type of the difference values of D is D::difference_type.
You can add another customization point template struct difference_type{ typedef typename T::difference_type; }; and specialize for the types not conforming to this trait.
To summarize, for a domain type Dom, Icl expects Dom(), <, ++, -- and if dom is a equidistant scalar type we expect an associated type Dom::difference_type to be defined.
This choice has not been taken for chrono::durations, which is a little inconsistent also, because interestingly for its chrono::time_point type the semantic is just the desired one.
Yes, you are surely right. time_point could have a default constructor, and have a epoch function. Howard, what do you think?
The possibility of default ctor customization is no remedy, because ICL should ideally be completely "chrono agnostic" and still interoperable. For the same reason duration::zero() is not an option.
You can always use a duration that has a representation that default construct to 0 and define the associated typedefs.
T3: chrono::time_point does not implement ++ and --. I assume this is because of the specific maths that is designed for chrono::time_points (P) and durations (D) where - : P x P -> D + : P x D -> P + : D x P -> P but + : P x P -> P //verboten
But this should not be an argument against ++ and -- because the "least steppable unit" for integral rep types as well as the "unit" for floating point rep types, that is processed by ++ and -- is the same for time_points and durations.
The problem with operators ++ and -- is that they should be equivalent to x+=1 and x-=1. As you can see there is no way if we are adding minutes, seconds, ... We could choose as default unit the one given by the duration parameter. If we added operators ++ and --, we should add time_point + Rep, Rep + time_point time_point - Rep, which are a little bit against the safety goals of Chrono. Hoping the proposals are close to the interoperability point. If the separated traits don't satisfy your design, maybe you could define a specific traits that groups all your needed traits. Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/chrono-Interoperability-with-ICL-and-comm... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Mar 15, 2011, at 2:00 PM, Vicente Botet wrote:
Joachim Faulhaber wrote:
To summarize, for a domain type Dom, Icl expects Dom(), <, ++, -- and if dom is a equidistant scalar type we expect an associated type Dom::difference_type to be defined.
This choice has not been taken for chrono::durations, which is a little inconsistent also, because interestingly for its chrono::time_point type the semantic is just the desired one.
Yes, you are surely right. time_point could have a default constructor, and have a epoch function. Howard, what do you think?
The current std::chrono::duration default constructor has this definition: constexpr duration() = default; The rationale for this is to give the client and the Rep author as many options as possible: typedef std::chrono::duration<long long> D; D d1; // d1.count() uninitialized - speed D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe typedef std::chrono::duration<BigInt> CustomD; CustomD d3; // d3.count() default constructed The author of BigInt may decide that 0 is the best default value. *Or* he might decide that nan is the best default value (personally I'd be tempted to go with nan). We did not want to dictate that a default-constructed duration always represented zero, as this decision would have dubious qualities from a safety point of view. For time_point a default constructed object is specifically documented to have the value "epoch", and duration's static zero() function is used to initialize it. It was felt this was more useful for time_point. Though time_point will most often be constructed from the value returned by now(). -Howard

2011/3/15 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 15, 2011, at 2:00 PM, Vicente Botet wrote:
Joachim Faulhaber wrote:
To summarize, for a domain type Dom, Icl expects Dom(), <, ++, -- and if dom is a equidistant scalar type we expect an associated type Dom::difference_type to be defined.
This choice has not been taken for chrono::durations, which is a little inconsistent also, because interestingly for its chrono::time_point type the semantic is just the desired one.
Yes, you are surely right. time_point could have a default constructor, and have a epoch function. Howard, what do you think?
The current std::chrono::duration default constructor has this definition:
constexpr duration() = default;
The rationale for this is to give the client and the Rep author as many options as possible:
typedef std::chrono::duration<long long> D;
D d1; // d1.count() uninitialized - speed D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
typedef std::chrono::duration<BigInt> CustomD;
CustomD d3; // d3.count() default constructed
Hi Howard, thanks for your comments. I understand the value and foresight of this flexible design. Yet from my point of view I would have chosen zero() as default and uninitialized as configurable option. But anyway, maybe its the more flexible and long lasting design to separate identity_element<T> and default ctor T(). Sine c++ is about speed, uninitialized could be the standard default for T() then. I'm kind a standard agnostic :( Maybe there is already something like a std::identity_element<T> ?
The author of BigInt may decide that 0 is the best default value. *Or* he might decide that nan is the best default value (personally I'd be tempted to go with nan).
Hmm, personally I'm a NaN hater. Although I basically think it's healthier to start loving the world one lives in (difficult at times, if one thinks of Japan). Maybe you can bring the enlightenment and beauty of NaN to me.
We did not want to dictate that a default-constructed duration always represented zero, as this decision would have dubious qualities from a safety point of view.
Not always, ok. But why not as a default?
For time_point a default constructed object is specifically documented to have the value "epoch", and duration's static zero() function is used to initialize it. It was felt this was more useful for time_point. Though time_point will most often be constructed from the value returned by now().
From an algebraic point of view, chrono::time_points (and durations) seem to be "pretty" isomorphic with the representing type Rep, which is a number. Roughly I'd expect that the following diagram will commute:
Let P : time_point R : Rep (representing type) f : P -> R forget Period information r : R -> P recall Period information g : functions on P and R P ---- g ----> P | | f = r | | V V R ---- g ----> R If functions g (additions, multiplications, .... and also compositions of them) are performed on time_points, and we take the Rep value this is the same, as if we take the Rep value and perform the same functions g on then and then go back to the time_points via recall function r. So all functions on P should be the isomorphic to the same function on R. If R() yields the identity_element on Rep, then also P() should yield an identity on time_point. Those are my thought about Chrono, correct me if I'm wrong. Thanks again, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

2011/3/15 Joachim Faulhaber <afojgo@googlemail.com>:
2011/3/15 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 15, 2011, at 2:00 PM, Vicente Botet wrote:
Joachim Faulhaber wrote:
To summarize, for a domain type Dom, Icl expects Dom(), <, ++, -- and if dom is a equidistant scalar type we expect an associated type Dom::difference_type to be defined.
This choice has not been taken for chrono::durations, which is a little inconsistent also, because interestingly for its chrono::time_point type the semantic is just the desired one.
Yes, you are surely right. time_point could have a default constructor, and have a epoch function. Howard, what do you think?
The current std::chrono::duration default constructor has this definition:
constexpr duration() = default;
The rationale for this is to give the client and the Rep author as many options as possible:
typedef std::chrono::duration<long long> D;
D d1; // d1.count() uninitialized - speed D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
typedef std::chrono::duration<BigInt> CustomD;
CustomD d3; // d3.count() default constructed
Hi Howard,
thanks for your comments. I understand the value and foresight of this flexible design. Yet from my point of view I would have chosen zero() as default and uninitialized as configurable option.
But anyway, maybe its the more flexible and long lasting design to separate identity_element<T> and default ctor T(). Sine c++ is about speed, uninitialized could be the standard default for T() then. I'm kind a standard agnostic :( Maybe there is already something like a std::identity_element<T> ?
The author of BigInt may decide that 0 is the best default value. *Or* he might decide that nan is the best default value (personally I'd be tempted to go with nan).
Hmm, personally I'm a NaN hater. Although I basically think it's healthier to start loving the world one lives in (difficult at times, if one thinks of Japan). Maybe you can bring the enlightenment and beauty of NaN to me.
We did not want to dictate that a default-constructed duration always represented zero, as this decision would have dubious qualities from a safety point of view.
Not always, ok. But why not as a default?
For time_point a default constructed object is specifically documented to have the value "epoch", and duration's static zero() function is used to initialize it. It was felt this was more useful for time_point. Though time_point will most often be constructed from the value returned by now().
From an algebraic point of view, chrono::time_points (and durations) seem to be "pretty" isomorphic with the representing type Rep, which is a number. Roughly I'd expect that the following diagram will commute:
Let P : time_point R : Rep (representing type) f : P -> R forget Period information r : R -> P recall Period information g : functions on P and R
P ---- g ----> P | | f = f | | V V R ---- g ----> R
If functions g (additions, multiplications, .... and also compositions of them) are performed on time_points, and we take the Rep value this is the same, as if we take the Rep value and perform the same functions g on them.
So all functions on P should be the isomorphic to the same function on R. If R() yields the identity_element on Rep, then also P() should yield an identity on time_point.
Those are my thought about Chrono, correct me if I'm wrong.
Ooops, corrections above. -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

Joachim Faulhaber wrote:
So all functions on P should be the isomorphic to the same function on R. If R() yields the identity_element on Rep, then also P() should yield an identity on time_point.
Those are my thought about Chrono, correct me if I'm wrong.
Joachim, I think that one of the goals of defining specific classes is to reduce the set of operations of the underlying type (Rep) to those that are safe and have a clear sens. That is, not all operations applicable to an int are applicable to a time_point. There is "Notes on programming" from Alexander Stepanovavailable here http://www.stepanovpapers.com/notes.pdf. I'm sure the reading of these notes will give you a lot of ideas ;-) (215 pages!!!) Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/chrono-Interoperability-with-ICL-and-comm... Sent from the Boost - Dev mailing list archive at Nabble.com.

Vicente Botet wrote:
There is "Notes on programming" from Alexander Stepanovavailable here http://www.stepanovpapers.com/notes.pdf. I'm sure the reading of these notes will give you a lot of ideas ;-) (215 pages!!!)
Beautiful! You made a "collateral victim of enthousiasm". (In other words, thanks for the pointer.) -Julian

2011/3/15 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 15, 2011, at 2:00 PM, Vicente Botet wrote:
The current std::chrono::duration default constructor has this definition:
constexpr duration() = default;
hmm, I'm a little confused now
The rationale for this is to give the client and the Rep author as many options as possible:
typedef std::chrono::duration<long long> D;
D d1; // d1.count() uninitialized - speed D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
This behavior is exactly what I desire
typedef std::chrono::duration<BigInt> CustomD;
CustomD d3; // d3.count() default constructed
But the current implementation of Boost.Chrono does not work like that: typedef std::chrono::duration<long long> D; D d2 = D(); // d2.count() UNINITIALIZED Will the semantics of
constexpr duration() = default;
implement the proposed behavior with the new standard? Regards, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

On Mar 16, 2011, at 8:50 AM, Joachim Faulhaber wrote:
2011/3/15 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 15, 2011, at 2:00 PM, Vicente Botet wrote:
The current std::chrono::duration default constructor has this definition:
constexpr duration() = default;
hmm, I'm a little confused now
The rationale for this is to give the client and the Rep author as many options as possible:
typedef std::chrono::duration<long long> D;
D d1; // d1.count() uninitialized - speed D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
This behavior is exactly what I desire
typedef std::chrono::duration<BigInt> CustomD;
CustomD d3; // d3.count() default constructed
But the current implementation of Boost.Chrono does not work like that:
typedef std::chrono::duration<long long> D; D d2 = D(); // d2.count() UNINITIALIZED
Will the semantics of
constexpr duration() = default;
implement the proposed behavior with the new standard?
Yes. I'm not sure if any compiler yet implements =default for default constructors. I'm hopeful that this feature will be widely implemented soon. It has the semantics of defining a compiler-generated default constructor, which you can only do in C++03 if you don't have any other constructors declared. -Howard

2011/3/16 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 16, 2011, at 8:50 AM, Joachim Faulhaber wrote:
2011/3/15 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 15, 2011, at 2:00 PM, Vicente Botet wrote:
The current std::chrono::duration default constructor has this definition:
constexpr duration() = default;
hmm, I'm a little confused now
The rationale for this is to give the client and the Rep author as many options as possible:
typedef std::chrono::duration<long long> D;
D d1; // d1.count() uninitialized - speed D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
This behavior is exactly what I desire
typedef std::chrono::duration<BigInt> CustomD;
CustomD d3; // d3.count() default constructed
But the current implementation of Boost.Chrono does not work like that:
typedef std::chrono::duration<long long> D; D d2 = D(); // d2.count() UNINITIALIZED
Will the semantics of
constexpr duration() = default;
implement the proposed behavior with the new standard?
Yes. I'm not sure if any compiler yet implements =default for default constructors. I'm hopeful that this feature will be widely implemented soon. It has the semantics of defining a compiler-generated default constructor, which you can only do in C++03 if you don't have any other constructors declared.
That's good to hear, so my wishes for durations default ctor behavior will be fulfilled at least in the future.
D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
BTW, I don't care for safety here at all. From my point of view I need some minimal information from an unknown type T to be able to express basic things like 0 < 1 where 0 and 1 are not available as literals or atomic expressions for T. Regards, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

On Mar 16, 2011, at 10:47 AM, Joachim Faulhaber wrote:
D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
BTW, I don't care for safety here at all. From my point of view I need some minimal information from an unknown type T to be able to express basic things like
0 < 1
where 0 and 1 are not available as literals or atomic expressions for T.
<nod> This is pretty much the rationale for duration_values<Rep>::zero(). There does not exist a duration_values<Rep>::one() mainly because the standardization of the <chrono> library was very difficult, with many interested parties, and one of the ways to get something like that done is to propose as little as possible. We didn't absolutely need one() to get timed sleeping and waiting going, and we had to keep the thread library as the main client of <chrono>, lest consensus would not have been achieved. Things like one() might be added via a future TR and/or standard. I'm already warming up my favorite additions for <chrono>. :-) http://home.roadrunner.com/~hinnant/duration_io/chrono_io.html http://home.roadrunner.com/~hinnant/duration_io/chrono_util.html -Howard

2011/3/16 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 16, 2011, at 10:47 AM, Joachim Faulhaber wrote:
D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
BTW, I don't care for safety here at all. From my point of view I need some minimal information from an unknown type T to be able to express basic things like
0 < 1
where 0 and 1 are not available as literals or atomic expressions for T.
<nod> This is pretty much the rationale for duration_values<Rep>::zero(). There does not exist a duration_values<Rep>::one()
I don't need a one() value if I get ++ T zero = T(); T one = T(); ++one; zero < one therefore I'd like to have it ;)
mainly because the standardization of the <chrono> library was very difficult, with many interested parties, and one of the ways to get something like that done is to propose as little as possible. We didn't absolutely need one() to get timed sleeping and waiting going, and we had to keep the thread library as the main client of <chrono>, lest consensus would not have been achieved. Things like one() might be added via a future TR and/or standard.
I've found that template<class T>struct identity_element{...}; template<class T>struct unit_element{...}; are useful generalizations of zero and one. And I think that an interval container library is not an adequate location for them.
I'm already warming up my favorite additions for <chrono>. :-)
http://home.roadrunner.com/~hinnant/duration_io/chrono_io.html http://home.roadrunner.com/~hinnant/duration_io/chrono_util.html
Good luck for them :) Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

Joachim Faulhaber wrote:
2011/3/16 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 16, 2011, at 8:50 AM, Joachim Faulhaber wrote:
2011/3/15 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 15, 2011, at 2:00 PM, Vicente Botet wrote:
The current std::chrono::duration default constructor has this definition:
constexpr duration() = default;
hmm, I'm a little confused now
The rationale for this is to give the client and the Rep author as many options as possible:
typedef std::chrono::duration D;
D d1; // d1.count() uninitialized - speed D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
This behavior is exactly what I desire
typedef std::chrono::duration CustomD;
CustomD d3; // d3.count() default constructed
But the current implementation of Boost.Chrono does not work like that:
typedef std::chrono::duration D; D d2 = D(); // d2.count() UNINITIALIZED
Will the semantics of
constexpr duration() = default;
implement the proposed behavior with the new standard?
Yes. I'm not sure if any compiler yet implements =default for default constructors. I'm hopeful that this feature will be widely implemented soon. It has the semantics of defining a compiler-generated default constructor, which you can only do in C++03 if you don't have any other constructors declared.
That's good to hear, so my wishes for durations default ctor behavior will be fulfilled at least in the future.
D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
Howard I have see this behavior with enum classes. It toke me a while to understand why the two preceding assignments results in different values, but after that it is the same as int i; int j= int(); It is extraneous however :( Joachim, it seems that you have found a Bug on the emulation of =default Boost.Chrono does. Please could you create a ticket. I think that the user could survive to a duration that is initialized to 0 even when the user has not requested it. Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/chrono-Interoperability-with-ICL-and-comm... Sent from the Boost - Dev mailing list archive at Nabble.com.

2011/3/16 Vicente Botet <vicente.botet@wanadoo.fr>:
Joachim Faulhaber wrote:
2011/3/16 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 16, 2011, at 8:50 AM, Joachim Faulhaber wrote:
2011/3/15 Howard Hinnant <howard.hinnant@gmail.com>:
On Mar 15, 2011, at 2:00 PM, Vicente Botet wrote:
The current std::chrono::duration default constructor has this definition:
constexpr duration() = default;
hmm, I'm a little confused now
The rationale for this is to give the client and the Rep author as many options as possible:
typedef std::chrono::duration D;
D d1; // d1.count() uninitialized - speed D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
This behavior is exactly what I desire
typedef std::chrono::duration CustomD;
CustomD d3; // d3.count() default constructed
But the current implementation of Boost.Chrono does not work like that:
typedef std::chrono::duration D; D d2 = D(); // d2.count() UNINITIALIZED
Will the semantics of
constexpr duration() = default;
implement the proposed behavior with the new standard?
Yes. I'm not sure if any compiler yet implements =default for default constructors. I'm hopeful that this feature will be widely implemented soon. It has the semantics of defining a compiler-generated default constructor, which you can only do in C++03 if you don't have any other constructors declared.
That's good to hear, so my wishes for durations default ctor behavior will be fulfilled at least in the future.
D d2 = D(); // d2.count() zero-initialized - safety if you believe 0 is safe
Howard I have see this behavior with enum classes. It toke me a while to understand why the two preceding assignments results in different values, but after that it is the same as
int i; int j= int();
It is extraneous however :(
Joachim, it seems that you have found a Bug on the emulation of =default Boost.Chrono does. Please could you create a ticket.
with pleasure :)
I think that the user could survive to a duration that is initialized to 0 even when the user has not requested it.
From my view (generic interoperability) it's the better choice than leaving it undefined in both cases.
Best, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

2011/3/15 Vicente Botet <vicente.botet@wanadoo.fr>:
Joachim Faulhaber wrote:
Currently I'm checking out the usage of chrono types with icl::intervals and interval containers. Obviously, using intervals of
[...]
I think it'd be ideal, if boost libraries interoperated with each other just out of the box, of course. To achive this, we have to find a common understanding of those concepts, that make a seamless interoperability work. I think, this is important work to be done, because it widens the view from one's own library perspective to a broader horizon of generic interplay.
Recall that adding an indirection use to solve a lot of problems.
Yeah ... alas I tend trying to use only as much indirection as necessary and as little as possible. Too much indirection may cost simplicity and readability of the code.
The problem: There is a minimal set of requirements that Icl expects for the domain types of intervals and interval containers (1) A zero element, more precisely an identity element w.r.t. the type's composition operation, which usually is +. An assumption that works well for all built in types and many STL-types is, that we get this element by the default constructor T().
What about creating a customization point identity or zero
template struct zero { T value() { return T(); } };
The user or Boost.Chrono could specialize it.
template <...> struct zero<duration<...> > { T value() { return duration<...>::zero(); } };
Yes, I already have a template of this kind template<...> struct identity_element So this is a solution for point (D1). A little awkward is the fact, that boost::chrono as "provider" library (it provides a type to be used in ICL), has the duty to implement customization code for the "recipient" library that uses chrono types as parameters. This implies that for every potential recipient library you are running the risk of facing customization point demands. Now I hope, that this will not be a real problem, because I think we are dealing here with only very few and pretty fundamental issues. Maybe it'd be better to lift something universal as an identity_element<T> to the level of boost/type_traits or (boost/algebra not yet there). Also to reduce the risk of reinventing the wheel namespace icl{ template<..> class identity_element ... } namespace foo{ template<..> class zero ... } // Same idea, different name
(2) A strict weak ordering < (3) For all discrete types and for continuous numeric types: Operators ++, -- (Only pre-variants needed e.g. ++x) (3.1) For discrete types ++/-- increments/decrements by a *least step* (3.2) For continuous numeric types ++/-- increments/decrements by a *unit step*.
The same can be done for customizations points increase_unit, and decrease_unit.
Well, in this case, I'd say, why wrap a simple function in a layer of indirection for a type, that, from an algebraic point of view is isomorphic to a number. A number that has incrementation and decrementation as a pretty fundamental function.
(4) For such equidistant scalar types D the ICL assumes, that the type of the difference values of D is D::difference_type.
You can add another customization point
template struct difference_type{ typedef typename T::difference_type; }; and specialize for the types not conforming to this trait.
Ok. I have a template for this too. Still I think, it'd be a little simpler to declare difference_type in chrono (1) Less code for the customization (2) My feeling is that it is almost standard to have an associated difference_type for a type like chrono::time_point. (3) because it's a model of a concept that I've called equidistant_scalar, basically a numeric type but without a fixed 0. duration : a more special associated type referring to all temporal equidistant_scalars difference_type : a more general associated type referring to all equidistant_scalars
T3: chrono::time_point does not implement ++ and --. I assume this is because of the specific maths that is designed for chrono::time_points (P) and durations (D) where - : P x P -> D + : P x D -> P + : D x P -> P but + : P x P -> P //verboten
But this should not be an argument against ++ and -- because the "least steppable unit" for integral rep types as well as the "unit" for floating point rep types, that is processed by ++ and -- is the same for time_points and durations.
The problem with operators ++ and -- is that they should be equivalent to x+=1 and x-=1. As you can see there is no way if we are adding minutes, seconds, ... We could choose as default unit the one given by the duration parameter.
I'm sorry not having studied Chrono's Periods thoroughly enough (I promise to catch up on it) but itsn't it true, that, for integral rep types, there is always a least steppable unit for all durations, that corresponds to the least steppable unit of the rep type?
Hoping the proposals are close to the interoperability point. If the separated traits don't satisfy your design, maybe you could define a specific traits that groups all your needed traits.
Thank you for your proposals. This is going in a good direction. And I personally think that the simpler solution, needing less indirections and less customization code may also be considered. Best regards, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

Joachim Faulhaber wrote:
2011/3/15 Vicente Botet <vicente.botet@wanadoo.fr>:
Hoping the proposals are close to the interoperability point. If the separated traits don't satisfy your design, maybe you could define a specific traits that groups all your needed traits.
Thank you for your proposals. This is going in a good direction. And I personally think that the simpler solution, needing less indirections and less customization code may also be considered.
I'm open to any evolution on Boost.Chrono that has a consensus, so I want to hear what others think ;-) In any case all the added functions should be accessible only if BOOST_CHRONO_EXTENSIONS is defined, so semantic compatibility with std::chrono is maintained. Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/chrono-Interoperability-with-ICL-and-comm... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Mar 15, 2011, at 4:39 PM, Joachim Faulhaber wrote:
2011/3/15 Vicente Botet <vicente.botet@wanadoo.fr>:
In any case all the added functions should be accessible only if BOOST_CHRONO_EXTENSIONS is defined, so semantic compatibility with std::chrono is maintained.
Is std::chrono already accepted and frozen in the new standard?
Technically nothing is frozen in the new standard as it hasn't been voted to FDIS yet. That could happen as soon as 11 days from now. But may not happen until this Summer or Fall, or even beyond (I hope not). I consider the std::chrono specification in the current working draft (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf) to be quite stable. To change it now would require a serious defect. New features (even new tweaks to existing features) are not being considered at this time. A new feature might be introduced via TR2 though. -Howard

Joachim Faulhaber wrote:
2011/3/15 Vicente Botet <vicente.botet@wanadoo.fr>:
In any case all the added functions should be accessible only if BOOST_CHRONO_EXTENSIONS is defined, so semantic compatibility with std::chrono is maintained.
Is std::chrono already accepted and frozen in the new standard?
It is accepted, and if I'm not wrong next week will be the next meeting for the C++ standard group, and I suspect that it should be the last one before the next c++0x is accepted. I guess that only bugs corrections are accepted now :( Howard should have more precise informations. Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/chrono-Interoperability-with-ICL-and-comm... Sent from the Boost - Dev mailing list archive at Nabble.com.

2011/3/15 Vicente Botet <vicente.botet@wanadoo.fr>:
Joachim Faulhaber wrote:
2011/3/15 Vicente Botet <vicente.botet@wanadoo.fr>:
In any case all the added functions should be accessible only if BOOST_CHRONO_EXTENSIONS is defined, so semantic compatibility with std::chrono is maintained.
Is std::chrono already accepted and frozen in the new standard?
It is accepted, and if I'm not wrong next week will be the next meeting for the C++ standard group, and I suspect that it should be the last one before the next c++0x is accepted. I guess that only bugs corrections are accepted now :(
This is unfortunate, since I intended to challenge its design fundamentally (just kidding) :-D
participants (5)
-
Howard Hinnant
-
Joachim Faulhaber
-
Julian Gonggrijp
-
Stewart, Robert
-
Vicente Botet