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