Boost logo

Boost :

Subject: Re: [boost] [chrono] Interoperability with ICL and common concepts
From: Joachim Faulhaber (afojgo_at_[hidden])
Date: 2011-03-15 16:14:42


2011/3/15 Vicente Botet <vicente.botet_at_[hidden]>:
>
> 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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk