
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