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