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