| 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 | { |
| 236 | 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 | { |
| 251 | 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 | { |
| 270 | 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 | { |
| 290 | 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; |
| 313 | 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 { |
| 343 | 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> { |
| 348 | 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> { |
| 353 | 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> { |
| 361 | 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> { |
| 369 | 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 | { |
| 383 | static BOOST_CONSTEXPR Rep zero() {return Rep(0);} |
| 384 | static BOOST_CHRONO_LIB_CONSTEXPR Rep max BOOST_PREVENT_MACRO_SUBSTITUTION () |
| 385 | { |
| 386 | return (std::numeric_limits<Rep>::max)(); |
| 387 | } |
| 388 | |
| 389 | 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 488 | rep count() const {return rep_;} |
| 489 | |
| 490 | // arithmetic |
| 491 | |
| 492 | BOOST_CONSTEXPR |
| 493 | duration operator+() const {return duration(rep_);;} |
| 494 | BOOST_CONSTEXPR |
| 495 | duration operator-() const {return duration(-rep_);} |
| 496 | duration& operator++() {++rep_; return *this;} |
| 497 | duration operator++(int) {return duration(rep_++);} |
| 498 | duration& operator--() {--rep_; return *this;} |
| 499 | duration operator--(int) {return duration(rep_--);} |
| 500 | |
| 501 | duration& operator+=(const duration& d) |
| 502 | { |
| 503 | rep_ += d.count(); return *this; |
| 504 | } |
| 505 | duration& operator-=(const duration& d) |
| 506 | { |
| 507 | rep_ -= d.count(); return *this; |
| 508 | } |
| 509 | |
| 510 | duration& operator*=(const rep& rhs) {rep_ *= rhs; return *this;} |
| 511 | duration& operator/=(const rep& rhs) {rep_ /= rhs; return *this;} |
| 512 | duration& operator%=(const rep& rhs) {rep_ %= rhs; return *this;} |
| 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 | |
| 519 | static BOOST_CONSTEXPR duration zero() |
| 520 | { |
| 521 | return duration(duration_values<rep>::zero()); |
| 522 | } |
| 523 | static BOOST_CHRONO_LIB_CONSTEXPR duration min BOOST_PREVENT_MACRO_SUBSTITUTION () |
| 524 | { |
| 525 | return duration((duration_values<rep>::min)()); |
| 526 | } |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 | { |
| 670 | 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 | { |
| 680 | 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 | { |
| 689 | 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 | { |
| 699 | 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 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 | |