
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