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