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