
Hi! My first goal in boostifying my proposed interval template library (ITL http://sourceforge.net/projects/itl) was to provide good examples for interval_sets and interval_maps using boost::date_time objects. This was much harder than I had expected, because incidentally the most important syntactical and semantical requirements that I do rely on for a parameter T of itl::interval<T> are not provided by boost::date_time. The one property of boost::date_time that knocked my socks off was the default constructor that 'is-not-a-date-time'. I paraphrase this as: boost::time is lacking a big bang ;-) Default constructors in nearly all the types that I've seen in my lifetime (I know the realm of my unknown unknowns is vast ;-) are intended to be elements of the type they do construct. Moreover in so many cases including built in types, default ctors serve as *initial elements*. Other elements can be *reached* from T() applying operations of T on them. This applies to all built in types and many std::types, like e.g. string, set, list etc. The most simple instance is unsigned int() with increment operation ++ that resembles the Peano axiomatic operations 0 and successor for natural numbers. This semantics of default ctors, at least in common built in and standard types and also in so many user defined types is so fundamental that I took it as a *semantical invariant* for the construction of my library. In the ITL an empty interval<T> [1,0] for instance, has to be defined generically: [ type<T>::unon(), type<T>::neutron() ] where type<T>::neutron() is implemented via T() : the default ctor and type<T>::unon() is implemented via ++T() : the default ctor incremented exactly once. So, striving to be as generic as possible I tried to set those minimal requirements that I assumed to be common sense: For discrete types T, the existence of an initial value T() and In(De)crementation. Instead of being a big bang of time, boost::date_times default constructors are cannibals. They give birth to a date_time() object that they immediately swallow. Then saying schizophrenic things about themselves like: cout << to_simple_string(ptime()); "not-a-date-time" They are singularities having an infinite gravitational pull on any operators. You can apply as many of them on the constructed black whole and they are never seen again having no effect. In addition to making the expected source of all elements of boost::date_time an awesome creature to be avoided, the universal c++ way of saying the next object within minimal distance '++' has also been taken away from me. May be with the good intension to prevent me from doing silly things like iterating over whole centuries in nanoseconds ;-) Yet all my applications of ++ and -- in my generic code use them only once like in comparing intervals of discrete types (a, b] == [c, d] is true, if(++a==c && b == d) that have different borders. I only have to make sure here that the minimal distance is proceeded only once. To summarize: What I have been relying on in my design, an initial default ctor T() and an increment operator ++ on the least availabel distance unit is exactly not provided by boost::date_time. Now the good news: Both libraries are so well designed that these seemingly contrarian designs can still be coupled with relatively small changes. Specifically, which is crucial for me, I can adapt my libraries code so that I can use all of boost::date_time in it's current form without patching anything (which would also work as I wrote in my last posting). The seemingly most decoupled remedy was, to implement the the missing functions type<T>::neutron() as well as increment ++ and decrement -- operators using the public interface of boost::date_time. This had to be done for every boost::date_time type like e.g. ptime: itl/ptime_adapter.hpp: ------------------------------------------------------------- boost::posix_time::ptime operator ++(boost::posix_time::ptime& x) { return x += boost::posix_time::ptime::time_duration_type::unit(); } boost::posix_time::ptime operator --(boost::posix_time::ptime& x) { return x -= boost::posix_time::ptime::time_duration_type::unit(); } template<> inline boost::posix_time::ptime type<boost::posix_time::ptime>::neutron() { return boost::posix_time::ptime(boost::posix_time::min_date_time); } ------------------------------------------------------------- Drawbacks of this are: (1) Designs are not completely decoupled, for every boost::a_date_time the matching adapterfunctions must be included. This is a complication for the usage. (2) *Every* generic library that relies on the existence of an initial default ctor and incrementation has to provide an adapter. (3) Every adapter has to be maintained, when boost::date_time is changed. (Kind of a distributed responsibility that is error prone) I would suggest, that a type that in it's basic characteristics resembles an intergral numeric type like boosts date_time types, that type should follow the concept Integral. cheers Joachim Interval Template Library download from http://sourceforge.net/projects/itl documentation http://www.herold-faulhaber.de/