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

source code of boost/libs/ratio/example/duration.hpp