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