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 | |