PageRenderTime 66ms CodeModel.GetById 13ms app.highlight 47ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/chrono/duration.hpp

http://hadesmem.googlecode.com/
C++ Header | 786 lines | 553 code | 112 blank | 121 comment | 10 complexity | 2bd62a4ee4b204fdda5da5da4174d661 MD5 | raw file
  1//  duration.hpp  --------------------------------------------------------------//
  2
  3//  Copyright 2008 Howard Hinnant
  4//  Copyright 2008 Beman Dawes
  5//  Copyright 2009-2010 Vicente J. Botet Escriba
  6
  7//  Distributed under the Boost Software License, Version 1.0.
  8//  See http://www.boost.org/LICENSE_1_0.txt
  9
 10/*
 11
 12This code was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
 13Many thanks to Howard for making his code available under the Boost license.
 14The original code was modified to conform to Boost conventions and to section
 1520.9 Time utilities [time] of the C++ committee's working paper N2798.
 16See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
 17
 18time2_demo contained this comment:
 19
 20    Much thanks to Andrei Alexandrescu,
 21                   Walter Brown,
 22                   Peter Dimov,
 23                   Jeff Garland,
 24                   Terry Golubiewski,
 25                   Daniel Krugler,
 26                   Anthony Williams.
 27*/
 28
 29
 30#ifndef BOOST_CHRONO_DURATION_HPP
 31#define BOOST_CHRONO_DURATION_HPP
 32
 33#include <boost/chrono/config.hpp>
 34#include <boost/chrono/detail/static_assert.hpp>
 35
 36#include <climits>
 37#include <limits>
 38
 39
 40#include <boost/mpl/logical.hpp>
 41#include <boost/ratio/ratio.hpp>
 42#include <boost/type_traits/common_type.hpp>
 43#include <boost/type_traits/is_arithmetic.hpp>
 44#include <boost/type_traits/is_convertible.hpp>
 45#include <boost/type_traits/is_floating_point.hpp>
 46#include <boost/type_traits/is_unsigned.hpp>
 47#include <boost/chrono/detail/is_evenly_divisible_by.hpp>
 48
 49#include <boost/cstdint.hpp>
 50#include <boost/utility/enable_if.hpp>
 51#include <boost/detail/workaround.hpp>
 52#include <boost/integer_traits.hpp>
 53
 54#if !defined(BOOST_NO_STATIC_ASSERT) || !defined(BOOST_CHRONO_USES_MPL_ASSERT)
 55#define BOOST_CHRONO_A_DURATION_REPRESENTATION_CAN_NOT_BE_A_DURATION        "A duration representation can not be a duration"
 56#define BOOST_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_DURATION_MUST_BE_A_STD_RATIO "Second template parameter of duration must be a boost::ratio"
 57#define BOOST_CHRONO_DURATION_PERIOD_MUST_BE_POSITIVE "duration period must be positive"
 58#define BOOST_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_TIME_POINT_MUST_BE_A_BOOST_CHRONO_DURATION "Second template parameter of time_point must be a boost::chrono::duration"
 59#endif
 60
 61
 62//----------------------------------------------------------------------------//
 63//                                                                            //
 64//                        20.9 Time utilities [time]                          //
 65//                                 synopsis                                   //
 66//                                                                            //
 67//----------------------------------------------------------------------------//
 68
 69namespace boost {
 70namespace chrono {
 71
 72    template <class Rep, class Period = ratio<1> >
 73    class duration;
 74
 75    namespace detail
 76    {
 77    template <class T>
 78      struct is_duration
 79        : boost::false_type {};
 80
 81    template <class Rep, class Period>
 82      struct is_duration<duration<Rep, Period> >
 83        : boost::true_type  {};
 84
 85    template <class Duration, class Rep, bool = is_duration<Rep>::value>
 86    struct duration_divide_result
 87    {
 88    };
 89
 90    template <class Duration, class Rep2,
 91        bool = (
 92                    ((boost::is_convertible<typename Duration::rep,
 93                        typename common_type<typename Duration::rep, Rep2>::type>::value))
 94                &&  ((boost::is_convertible<Rep2,
 95                        typename common_type<typename Duration::rep, Rep2>::type>::value))
 96                )
 97        >
 98    struct duration_divide_imp
 99    {
100    };
101
102    template <class Rep1, class Period, class Rep2>
103    struct duration_divide_imp<duration<Rep1, Period>, Rep2, true>
104    {
105        typedef duration<typename common_type<Rep1, Rep2>::type, Period> type;
106    };
107
108    template <class Rep1, class Period, class Rep2>
109    struct duration_divide_result<duration<Rep1, Period>, Rep2, false>
110        : duration_divide_imp<duration<Rep1, Period>, Rep2>
111    {
112    };
113
114///
115    template <class Rep, class Duration, bool = is_duration<Rep>::value>
116    struct duration_divide_result2
117    {
118    };
119
120    template <class Rep, class Duration,
121        bool = (
122                    ((boost::is_convertible<typename Duration::rep,
123                        typename common_type<typename Duration::rep, Rep>::type>::value))
124                &&  ((boost::is_convertible<Rep,
125                        typename common_type<typename Duration::rep, Rep>::type>::value))
126                )
127        >
128    struct duration_divide_imp2
129    {
130    };
131
132    template <class Rep1, class Rep2, class Period >
133    struct duration_divide_imp2<Rep1, duration<Rep2, Period>, true>
134    {
135        //typedef typename common_type<Rep1, Rep2>::type type;
136        typedef double type;
137    };
138
139    template <class Rep1, class Rep2, class Period >
140    struct duration_divide_result2<Rep1, duration<Rep2, Period>, false>
141        : duration_divide_imp2<Rep1, duration<Rep2, Period> >
142    {
143    };
144
145///
146    template <class Duration, class Rep, bool = is_duration<Rep>::value>
147    struct duration_modulo_result
148    {
149    };
150
151    template <class Duration, class Rep2,
152        bool = (
153                    //boost::is_convertible<typename Duration::rep,
154                        //typename common_type<typename Duration::rep, Rep2>::type>::value
155                //&&
156    boost::is_convertible<Rep2,
157                        typename common_type<typename Duration::rep, Rep2>::type>::value
158                )
159        >
160    struct duration_modulo_imp
161    {
162    };
163
164    template <class Rep1, class Period, class Rep2>
165    struct duration_modulo_imp<duration<Rep1, Period>, Rep2, true>
166    {
167        typedef duration<typename common_type<Rep1, Rep2>::type, Period> type;
168    };
169
170    template <class Rep1, class Period, class Rep2>
171    struct duration_modulo_result<duration<Rep1, Period>, Rep2, false>
172        : duration_modulo_imp<duration<Rep1, Period>, Rep2>
173    {
174    };
175
176} // namespace detail
177} // namespace chrono
178
179
180// common_type trait specializations
181
182template <class Rep1, class Period1, class Rep2, class Period2>
183struct common_type<chrono::duration<Rep1, Period1>,
184                     chrono::duration<Rep2, Period2> >;
185
186
187namespace chrono {
188
189    // customization traits
190    template <class Rep> struct treat_as_floating_point;
191    template <class Rep> struct duration_values;
192
193    // convenience typedefs
194    typedef duration<boost::int_least64_t, nano> nanoseconds;    // at least 64 bits needed
195    typedef duration<boost::int_least64_t, micro> microseconds;  // at least 55 bits needed
196    typedef duration<boost::int_least64_t, milli> milliseconds;  // at least 45 bits needed
197    typedef duration<boost::int_least64_t> seconds;              // at least 35 bits needed
198    typedef duration<boost::int_least32_t, ratio< 60> > minutes; // at least 29 bits needed
199    typedef duration<boost::int_least32_t, ratio<3600> > hours;  // at least 23 bits needed
200
201//----------------------------------------------------------------------------//
202//                          duration helpers                                  //
203//----------------------------------------------------------------------------//
204
205namespace detail
206{
207
208    // duration_cast
209
210    // duration_cast is the heart of this whole prototype.  It can convert any
211    //   duration to any other.  It is also (implicitly) used in converting
212    //   time_points.  The conversion is always exact if possible.  And it is
213    //   always as efficient as hand written code.  If different representations
214    //   are involved, care is taken to never require implicit conversions.
215    //   Instead static_cast is used explicitly for every required conversion.
216    //   If there are a mixture of integral and floating point representations,
217    //   the use of common_type ensures that the most logical "intermediate"
218    //   representation is used.
219    template <class FromDuration, class ToDuration,
220              class Period,
221              bool PeriodNumEq1,
222              bool PeriodDenEq1>
223    struct duration_cast_aux;
224
225    // When the two periods are the same, all that is left to do is static_cast from
226    //   the source representation to the target representation (which may be a no-op).
227    //   This conversion is always exact as long as the static_cast from the source
228    //   representation to the destination representation is exact.
229    template <class FromDuration, class ToDuration, class Period>
230    struct duration_cast_aux<FromDuration, ToDuration, Period, true, true>
231    {
232        BOOST_CHRONO_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
233        {
234            return ToDuration(static_cast<typename ToDuration::rep>(fd.count()));
235        }
236    };
237
238    // When the numerator of FromPeriod / ToPeriod is 1, then all we need to do is
239    //   divide by the denominator of FromPeriod / ToPeriod.  The common_type of
240    //   the two representations is used for the intermediate computation before
241    //   static_cast'ing to the destination.
242    //   This conversion is generally not exact because of the division (but could be
243    //   if you get lucky on the run time value of fd.count()).
244    template <class FromDuration, class ToDuration, class Period>
245    struct duration_cast_aux<FromDuration, ToDuration, Period, true, false>
246    {
247        BOOST_CHRONO_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
248        {
249            typedef typename common_type<
250                typename ToDuration::rep,
251                typename FromDuration::rep,
252                boost::intmax_t>::type C;
253            return ToDuration(static_cast<typename ToDuration::rep>(
254                              static_cast<C>(fd.count()) / static_cast<C>(Period::den)));
255        }
256    };
257
258    // When the denomenator of FromPeriod / ToPeriod is 1, then all we need to do is
259    //   multiply by the numerator of FromPeriod / ToPeriod.  The common_type of
260    //   the two representations is used for the intermediate computation before
261    //   static_cast'ing to the destination.
262    //   This conversion is always exact as long as the static_cast's involved are exact.
263    template <class FromDuration, class ToDuration, class Period>
264    struct duration_cast_aux<FromDuration, ToDuration, Period, false, true>
265    {
266        BOOST_CHRONO_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
267        {
268            typedef typename common_type<
269              typename ToDuration::rep,
270              typename FromDuration::rep,
271              boost::intmax_t>::type C;
272            return ToDuration(static_cast<typename ToDuration::rep>(
273                              static_cast<C>(fd.count()) * static_cast<C>(Period::num)));
274        }
275    };
276
277    // When neither the numerator or denominator of FromPeriod / ToPeriod is 1, then we need to
278    //   multiply by the numerator and divide by the denominator of FromPeriod / ToPeriod.  The
279    //   common_type of the two representations is used for the intermediate computation before
280    //   static_cast'ing to the destination.
281    //   This conversion is generally not exact because of the division (but could be
282    //   if you get lucky on the run time value of fd.count()).
283    template <class FromDuration, class ToDuration, class Period>
284    struct duration_cast_aux<FromDuration, ToDuration, Period, false, false>
285    {
286        BOOST_CHRONO_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
287        {
288            typedef typename common_type<
289              typename ToDuration::rep,
290              typename FromDuration::rep,
291              boost::intmax_t>::type C;
292            return ToDuration(static_cast<typename ToDuration::rep>(
293               static_cast<C>(fd.count()) * static_cast<C>(Period::num)
294                 / static_cast<C>(Period::den)));
295        }
296    };
297
298    template <class FromDuration, class ToDuration>
299    struct duration_cast {
300        typedef typename ratio_divide<typename FromDuration::period,
301              typename ToDuration::period>::type Period;
302        typedef duration_cast_aux<
303            FromDuration,
304            ToDuration,
305            Period,
306            Period::num == 1,
307            Period::den == 1
308        > Aux;
309        BOOST_CHRONO_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
310        {
311            return Aux()(fd);
312        }
313    };
314
315} // namespace detail
316
317//----------------------------------------------------------------------------//
318//                                                                            //
319//      20.9.2 Time-related traits [time.traits]                              //
320//                                                                            //
321//----------------------------------------------------------------------------//
322//----------------------------------------------------------------------------//
323//      20.9.2.1 treat_as_floating_point [time.traits.is_fp]                        //
324//      Probably should have been treat_as_floating_point. Editor notifed.    //
325//----------------------------------------------------------------------------//
326
327    // Support bidirectional (non-exact) conversions for floating point rep types
328    //   (or user defined rep types which specialize treat_as_floating_point).
329    template <class Rep>
330    struct treat_as_floating_point : boost::is_floating_point<Rep> {};
331
332//----------------------------------------------------------------------------//
333//      20.9.2.2 duration_values [time.traits.duration_values]                //
334//----------------------------------------------------------------------------//
335
336namespace detail {
337    template <class T, bool = is_arithmetic<T>::value>
338    struct chrono_numeric_limits {
339        static T lowest() throw() {return (std::numeric_limits<T>::min)  ();}
340    };
341
342    template <class T>
343    struct chrono_numeric_limits<T,true> {
344        static T lowest() throw() {return (std::numeric_limits<T>::min)  ();}
345    };
346
347    template <>
348    struct chrono_numeric_limits<float,true> {
349        static float lowest() throw()
350        {
351            return -(std::numeric_limits<float>::max) ();
352        }
353    };
354
355    template <>
356    struct chrono_numeric_limits<double,true> {
357        static double lowest() throw()
358        {
359            return -(std::numeric_limits<double>::max) ();
360        }
361    };
362
363    template <>
364    struct chrono_numeric_limits<long double,true> {
365        static long double lowest() throw()
366        {
367            return -(std::numeric_limits<long double>::max)();
368        }
369    };
370
371    template <class T>
372    struct numeric_limits : chrono_numeric_limits<typename remove_cv<T>::type>
373    {};
374
375}
376template <class Rep>
377struct duration_values
378{
379    static BOOST_CHRONO_CONSTEXPR Rep zero() {return Rep(0);}
380    static BOOST_CHRONO_CONSTEXPR Rep max BOOST_PREVENT_MACRO_SUBSTITUTION ()
381    {
382        return (std::numeric_limits<Rep>::max)();
383    }
384
385    static BOOST_CHRONO_CONSTEXPR Rep min BOOST_PREVENT_MACRO_SUBSTITUTION ()
386    {
387        return detail::numeric_limits<Rep>::lowest();
388    }
389};
390
391}  // namespace chrono
392
393//----------------------------------------------------------------------------//
394//      20.9.2.3 Specializations of common_type [time.traits.specializations] //
395//----------------------------------------------------------------------------//
396
397template <class Rep1, class Period1, class Rep2, class Period2>
398struct common_type<chrono::duration<Rep1, Period1>,
399                   chrono::duration<Rep2, Period2> >
400{
401  typedef chrono::duration<typename common_type<Rep1, Rep2>::type,
402                      typename boost::ratio_gcd<Period1, Period2>::type> type;
403};
404
405
406//----------------------------------------------------------------------------//
407//                                                                            //
408//         20.9.3 Class template duration [time.duration]                     //
409//                                                                            //
410//----------------------------------------------------------------------------//
411
412
413namespace chrono {
414
415    template <class Rep, class Period>
416    class duration
417    {
418    //BOOST_CHRONO_STATIC_ASSERT(boost::is_integral<Rep>::value, BOOST_CHRONO_A_DURATION_REPRESENTATION_MUST_BE_INTEGRAL, ());
419    BOOST_CHRONO_STATIC_ASSERT(!boost::chrono::detail::is_duration<Rep>::value,
420            BOOST_CHRONO_A_DURATION_REPRESENTATION_CAN_NOT_BE_A_DURATION, ());
421    BOOST_CHRONO_STATIC_ASSERT(boost::ratio_detail::is_ratio<typename Period::type>::value,
422            BOOST_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_DURATION_MUST_BE_A_STD_RATIO, ());
423    BOOST_CHRONO_STATIC_ASSERT(Period::num>0,
424            BOOST_CHRONO_DURATION_PERIOD_MUST_BE_POSITIVE, ());
425    public:
426        typedef Rep rep;
427        typedef Period period;
428    private:
429        rep rep_;
430    public:
431
432        BOOST_CHRONO_CONSTEXPR
433      duration() : rep_(duration_values<rep>::zero()) { }
434        template <class Rep2>
435        BOOST_CHRONO_CONSTEXPR
436        explicit duration(const Rep2& r
437        , typename boost::enable_if <
438                    mpl::and_ <
439                        boost::is_convertible<Rep2, rep>,
440                        mpl::or_ <
441                            treat_as_floating_point<rep>,
442                            mpl::and_ <
443                                mpl::not_ < treat_as_floating_point<rep> >,
444                                mpl::not_ < treat_as_floating_point<Rep2> >
445                            >
446                        >
447                    >
448                >::type* = 0
449        ) : rep_(r) { }
450        ~duration() {} //= default;
451        duration(const duration& rhs) : rep_(rhs.rep_) {} // = default;
452        duration& operator=(const duration& rhs) // = default;
453        {
454            if (&rhs != this) rep_= rhs.rep_;
455            return *this;
456        }
457
458        // conversions
459        template <class Rep2, class Period2>
460        BOOST_CHRONO_CONSTEXPR
461        duration(const duration<Rep2, Period2>& d
462        , typename boost::enable_if <
463                    mpl::or_ <
464                        treat_as_floating_point<rep>,
465                        mpl::and_ <
466                            chrono_detail::is_evenly_divisible_by<Period2, period>,
467                            mpl::not_ < treat_as_floating_point<Rep2> >
468                        >
469                    >
470                >::type* = 0
471        )
472            : rep_(chrono::detail::duration_cast<duration<Rep2, Period2>, duration>()(d).count()) {}
473
474        // observer
475
476        BOOST_CHRONO_CONSTEXPR
477        rep count() const {return rep_;}
478
479        // arithmetic
480
481        BOOST_CHRONO_CONSTEXPR
482        duration  operator+() const {return *this;}
483        BOOST_CHRONO_CONSTEXPR
484        duration  operator-() const {return duration(-rep_);}
485        duration& operator++()      {++rep_; return *this;}
486        duration  operator++(int)   {return duration(rep_++);}
487        duration& operator--()      {--rep_; return *this;}
488        duration  operator--(int)   {return duration(rep_--);}
489
490        duration& operator+=(const duration& d)
491        {
492            rep_ += d.count(); return *this;
493        }
494        duration& operator-=(const duration& d)
495        {
496            rep_ -= d.count(); return *this;
497        }
498
499        duration& operator*=(const rep& rhs) {rep_ *= rhs; return *this;}
500        duration& operator/=(const rep& rhs) {rep_ /= rhs; return *this;}
501        duration& operator%=(const rep& rhs) {rep_ %= rhs; return *this;}
502        duration& operator%=(const duration& rhs)
503        {
504            rep_ %= rhs.count(); return *this;
505        }
506        // 20.9.3.4 duration special values [time.duration.special]
507
508        static BOOST_CHRONO_CONSTEXPR duration zero()
509        {
510            return duration(duration_values<rep>::zero());
511        }
512        static BOOST_CHRONO_CONSTEXPR duration min BOOST_PREVENT_MACRO_SUBSTITUTION ()
513        {
514            return duration((duration_values<rep>::min)());
515        }
516        static BOOST_CHRONO_CONSTEXPR duration max BOOST_PREVENT_MACRO_SUBSTITUTION ()
517        {
518            return duration((duration_values<rep>::max)());
519        }
520    };
521
522//----------------------------------------------------------------------------//
523//      20.9.3.5 duration non-member arithmetic [time.duration.nonmember]     //
524//----------------------------------------------------------------------------//
525
526    // Duration +
527
528    template <class Rep1, class Period1, class Rep2, class Period2>
529    inline
530    typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
531    operator+(const duration<Rep1, Period1>& lhs,
532          const duration<Rep2, Period2>& rhs)
533    {
534      typename common_type<duration<Rep1, Period1>,
535        duration<Rep2, Period2> >::type result = lhs;
536      result += rhs;
537      return result;
538    }
539
540    // Duration -
541
542    template <class Rep1, class Period1, class Rep2, class Period2>
543    inline
544    typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
545    operator-(const duration<Rep1, Period1>& lhs,
546          const duration<Rep2, Period2>& rhs)
547    {
548        typename common_type<duration<Rep1, Period1>,
549            duration<Rep2, Period2> >::type result = lhs;
550        result -= rhs;
551        return result;
552    }
553
554    // Duration *
555
556    template <class Rep1, class Period, class Rep2>
557    inline
558    typename boost::enable_if <
559        mpl::and_ <
560        boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>,
561        boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>
562        >,
563        duration<typename common_type<Rep1, Rep2>::type, Period>
564    >::type
565    operator*(const duration<Rep1, Period>& d, const Rep2& s)
566    {
567        typedef typename common_type<Rep1, Rep2>::type CR;
568            duration<CR, Period> r = d;
569        r *= static_cast<CR>(s);
570        return r;
571    }
572
573    template <class Rep1, class Period, class Rep2>
574    inline
575    typename boost::enable_if <
576        mpl::and_ <
577        boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>,
578        boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>
579        >,
580        duration<typename common_type<Rep1, Rep2>::type, Period>
581    >::type
582    operator*(const Rep1& s, const duration<Rep2, Period>& d)
583    {
584        return d * s;
585    }
586
587    // Duration /
588
589    template <class Rep1, class Period, class Rep2>
590    inline
591    typename boost::disable_if <boost::chrono::detail::is_duration<Rep2>,
592      typename boost::chrono::detail::duration_divide_result<
593        duration<Rep1, Period>, Rep2>::type
594    >::type
595    operator/(const duration<Rep1, Period>& d, const Rep2& s)
596    {
597        typedef typename common_type<Rep1, Rep2>::type CR;
598          duration<CR, Period> r = d;
599        r /= static_cast<CR>(s);
600        return r;
601    }
602
603    template <class Rep1, class Period1, class Rep2, class Period2>
604    inline
605    typename common_type<Rep1, Rep2>::type
606    operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
607    {
608        typedef typename common_type<duration<Rep1, Period1>,
609                                   duration<Rep2, Period2> >::type CD;
610        return CD(lhs).count() / CD(rhs).count();
611    }
612
613    #ifdef BOOST_CHRONO_EXTENSIONS
614    template <class Rep1, class Rep2, class Period>
615    inline
616    typename boost::disable_if <boost::chrono::detail::is_duration<Rep1>,
617      typename boost::chrono::detail::duration_divide_result2<
618        Rep1, duration<Rep2, Period> >::type
619      >::type
620    operator/(const Rep1& s, const duration<Rep2, Period>& d)
621    {
622        typedef typename common_type<Rep1, Rep2>::type CR;
623        duration<CR, Period> r = d;
624        return  static_cast<CR>(s)/r.count();
625    }
626    #endif
627    // Duration %
628
629    template <class Rep1, class Period, class Rep2>
630    typename boost::disable_if <boost::chrono::detail::is_duration<Rep2>,
631      typename boost::chrono::detail::duration_modulo_result<
632        duration<Rep1, Period>, Rep2>::type
633    >::type
634    operator%(const duration<Rep1, Period>& d, const Rep2& s)
635    {
636        typedef typename common_type<Rep1, Rep2>::type CR;
637        duration<CR, Period> r = d;
638        r %= static_cast<CR>(s);
639        return r;
640    }
641
642    template <class Rep1, class Period1, class Rep2, class Period2>
643    typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
644    operator%(const duration<Rep1, Period1>& lhs,
645          const duration<Rep2, Period2>& rhs) {
646        typedef typename common_type<duration<Rep1, Period1>,
647                                 duration<Rep2, Period2> >::type CD;
648        CD r(lhs);
649        r%=CD(rhs);
650        return r;
651    }
652
653
654//----------------------------------------------------------------------------//
655//      20.9.3.6 duration comparisons [time.duration.comparisons]             //
656//----------------------------------------------------------------------------//
657
658namespace detail
659{
660    template <class LhsDuration, class RhsDuration>
661    struct duration_eq
662    {
663        bool operator()(const LhsDuration& lhs, const RhsDuration& rhs)
664        {
665            typedef typename common_type<LhsDuration, RhsDuration>::type CD;
666            return CD(lhs).count() == CD(rhs).count();
667        }
668    };
669
670    template <class LhsDuration>
671    struct duration_eq<LhsDuration, LhsDuration>
672    {
673        bool operator()(const LhsDuration& lhs, const LhsDuration& rhs)
674        {
675            return lhs.count() == rhs.count();
676        }
677    };
678
679    template <class LhsDuration, class RhsDuration>
680    struct duration_lt
681    {
682        bool operator()(const LhsDuration& lhs, const RhsDuration& rhs)
683        {
684            typedef typename common_type<LhsDuration, RhsDuration>::type CD;
685            return CD(lhs).count() < CD(rhs).count();
686        }
687    };
688
689    template <class LhsDuration>
690    struct duration_lt<LhsDuration, LhsDuration>
691    {
692        bool operator()(const LhsDuration& lhs, const LhsDuration& rhs)
693        {
694            return lhs.count() < rhs.count();
695        }
696    };
697
698} // namespace detail
699
700    // Duration ==
701
702    template <class Rep1, class Period1, class Rep2, class Period2>
703    inline BOOST_CHRONO_CONSTEXPR
704    bool
705    operator==(const duration<Rep1, Period1>& lhs,
706          const duration<Rep2, Period2>& rhs)
707    {
708        return boost::chrono::detail::duration_eq<
709            duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs);
710    }
711
712    // Duration !=
713
714    template <class Rep1, class Period1, class Rep2, class Period2>
715    inline BOOST_CHRONO_CONSTEXPR
716    bool
717    operator!=(const duration<Rep1, Period1>& lhs,
718          const duration<Rep2, Period2>& rhs)
719    {
720        return !(lhs == rhs);
721    }
722
723    // Duration <
724
725    template <class Rep1, class Period1, class Rep2, class Period2>
726    inline BOOST_CHRONO_CONSTEXPR
727    bool
728    operator< (const duration<Rep1, Period1>& lhs,
729          const duration<Rep2, Period2>& rhs)
730    {
731        return boost::chrono::detail::duration_lt<
732          duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs);
733    }
734
735    // Duration >
736
737    template <class Rep1, class Period1, class Rep2, class Period2>
738    inline BOOST_CHRONO_CONSTEXPR
739    bool
740    operator> (const duration<Rep1, Period1>& lhs,
741          const duration<Rep2, Period2>& rhs)
742    {
743        return rhs < lhs;
744    }
745
746    // Duration <=
747
748    template <class Rep1, class Period1, class Rep2, class Period2>
749    inline BOOST_CHRONO_CONSTEXPR
750    bool
751    operator<=(const duration<Rep1, Period1>& lhs,
752          const duration<Rep2, Period2>& rhs)
753    {
754        return !(rhs < lhs);
755    }
756
757    // Duration >=
758
759    template <class Rep1, class Period1, class Rep2, class Period2>
760    inline
761    bool
762    operator>=(const duration<Rep1, Period1>& lhs,
763          const duration<Rep2, Period2>& rhs)
764    {
765        return !(lhs < rhs);
766    }
767
768//----------------------------------------------------------------------------//
769//      20.9.3.7 duration_cast [time.duration.cast]                           //
770//----------------------------------------------------------------------------//
771
772    // Compile-time select the most efficient algorithm for the conversion...
773    template <class ToDuration, class Rep, class Period>
774    inline BOOST_CHRONO_CONSTEXPR
775    typename boost::enable_if <
776      boost::chrono::detail::is_duration<ToDuration>, ToDuration>::type
777    duration_cast(const duration<Rep, Period>& fd)
778    {
779        return boost::chrono::detail::duration_cast<
780          duration<Rep, Period>, ToDuration>()(fd);
781    }
782
783} // namespace chrono
784} // namespace boost
785
786#endif // BOOST_CHRONO_DURATION_HPP