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