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_NO_CXX11_DEFAULTED_FUNCTIONS || \ |
437 | defined BOOST_CHRONO_DURATION_DEFAULTS_TO_ZERO |
438 | BOOST_FORCEINLINE BOOST_CONSTEXPR |
439 | duration() : rep_(duration_values<rep>::zero()) { } |
440 | #else |
441 | BOOST_CONSTEXPR duration() BOOST_NOEXCEPT {}; |
442 | #endif |
443 | template <class Rep2> |
444 | BOOST_SYMBOL_VISIBLE BOOST_FORCEINLINE BOOST_CONSTEXPR |
445 | explicit duration(const Rep2& r |
446 | , typename boost::enable_if < |
447 | mpl::and_ < |
448 | boost::is_convertible<Rep2, rep>, |
449 | mpl::or_ < |
450 | treat_as_floating_point<rep>, |
451 | mpl::and_ < |
452 | mpl::not_ < treat_as_floating_point<rep> >, |
453 | mpl::not_ < treat_as_floating_point<Rep2> > |
454 | > |
455 | > |
456 | > |
457 | >::type* = 0 |
458 | ) : rep_(r) { } |
459 | #if defined BOOST_NO_CXX11_DEFAULTED_FUNCTIONS |
460 | duration& operator=(const duration& rhs) |
461 | { |
462 | if (&rhs != this) rep_= rhs.rep_; |
463 | return *this; |
464 | } |
465 | #else |
466 | duration& operator=(const duration& rhs) = default; |
467 | #endif |
468 | // conversions |
469 | template <class Rep2, class Period2> |
470 | BOOST_FORCEINLINE BOOST_CONSTEXPR |
471 | duration(const duration<Rep2, Period2>& d |
472 | , typename boost::enable_if < |
473 | mpl::or_ < |
474 | treat_as_floating_point<rep>, |
475 | mpl::and_ < |
476 | chrono_detail::is_evenly_divisible_by<Period2, period>, |
477 | mpl::not_ < treat_as_floating_point<Rep2> > |
478 | > |
479 | > |
480 | >::type* = 0 |
481 | ) |
482 | : rep_(chrono::detail::duration_cast<duration<Rep2, Period2>, duration>()(d).count()) {} |
483 | |
484 | // observer |
485 | |
486 | BOOST_CONSTEXPR |
487 | rep count() const {return rep_;} |
488 | |
489 | // arithmetic |
490 | |
491 | BOOST_CONSTEXPR |
492 | duration operator+() const {return duration(rep_);;} |
493 | BOOST_CONSTEXPR |
494 | duration operator-() const {return duration(-rep_);} |
495 | duration& operator++() {++rep_; return *this;} |
496 | duration operator++(int) {return duration(rep_++);} |
497 | duration& operator--() {--rep_; return *this;} |
498 | duration operator--(int) {return duration(rep_--);} |
499 | |
500 | duration& operator+=(const duration& d) |
501 | { |
502 | rep_ += d.count(); return *this; |
503 | } |
504 | duration& operator-=(const duration& d) |
505 | { |
506 | rep_ -= d.count(); return *this; |
507 | } |
508 | |
509 | duration& operator*=(const rep& rhs) {rep_ *= rhs; return *this;} |
510 | duration& operator/=(const rep& rhs) {rep_ /= rhs; return *this;} |
511 | duration& operator%=(const rep& rhs) {rep_ %= rhs; return *this;} |
512 | duration& operator%=(const duration& rhs) |
513 | { |
514 | rep_ %= rhs.count(); return *this; |
515 | } |
516 | // 20.9.3.4 duration special values [time.duration.special] |
517 | |
518 | static BOOST_CONSTEXPR duration zero() |
519 | { |
520 | return duration(duration_values<rep>::zero()); |
521 | } |
522 | static BOOST_CHRONO_LIB_CONSTEXPR duration min BOOST_PREVENT_MACRO_SUBSTITUTION () |
523 | { |
524 | return duration((duration_values<rep>::min)()); |
525 | } |
526 | static BOOST_CHRONO_LIB_CONSTEXPR duration max BOOST_PREVENT_MACRO_SUBSTITUTION () |
527 | { |
528 | return duration((duration_values<rep>::max)()); |
529 | } |
530 | }; |
531 | |
532 | //----------------------------------------------------------------------------// |
533 | // 20.9.3.5 duration non-member arithmetic [time.duration.nonmember] // |
534 | //----------------------------------------------------------------------------// |
535 | |
536 | // Duration + |
537 | |
538 | template <class Rep1, class Period1, class Rep2, class Period2> |
539 | inline BOOST_CONSTEXPR |
540 | typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type |
541 | operator+(const duration<Rep1, Period1>& lhs, |
542 | const duration<Rep2, Period2>& rhs) |
543 | { |
544 | typedef typename common_type<duration<Rep1, Period1>, |
545 | duration<Rep2, Period2> >::type CD; |
546 | return CD(CD(lhs).count()+CD(rhs).count()); |
547 | } |
548 | |
549 | // Duration - |
550 | |
551 | template <class Rep1, class Period1, class Rep2, class Period2> |
552 | inline BOOST_CONSTEXPR |
553 | typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type |
554 | operator-(const duration<Rep1, Period1>& lhs, |
555 | const duration<Rep2, Period2>& rhs) |
556 | { |
557 | typedef typename common_type<duration<Rep1, Period1>, |
558 | duration<Rep2, Period2> >::type CD; |
559 | return CD(CD(lhs).count()-CD(rhs).count()); |
560 | } |
561 | |
562 | // Duration * |
563 | |
564 | template <class Rep1, class Period, class Rep2> |
565 | inline BOOST_CONSTEXPR |
566 | typename boost::enable_if < |
567 | mpl::and_ < |
568 | boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>, |
569 | boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type> |
570 | >, |
571 | duration<typename common_type<Rep1, Rep2>::type, Period> |
572 | >::type |
573 | operator*(const duration<Rep1, Period>& d, const Rep2& s) |
574 | { |
575 | typedef typename common_type<Rep1, Rep2>::type CR; |
576 | typedef duration<CR, Period> CD; |
577 | return CD(CD(d).count()*static_cast<CR>(s)); |
578 | } |
579 | |
580 | template <class Rep1, class Period, class Rep2> |
581 | inline BOOST_CONSTEXPR |
582 | typename boost::enable_if < |
583 | mpl::and_ < |
584 | boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>, |
585 | boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type> |
586 | >, |
587 | duration<typename common_type<Rep1, Rep2>::type, Period> |
588 | >::type |
589 | operator*(const Rep1& s, const duration<Rep2, Period>& d) |
590 | { |
591 | return d * s; |
592 | } |
593 | |
594 | // Duration / |
595 | |
596 | template <class Rep1, class Period, class Rep2> |
597 | inline BOOST_CONSTEXPR |
598 | typename boost::disable_if <boost::chrono::detail::is_duration<Rep2>, |
599 | typename boost::chrono::detail::duration_divide_result< |
600 | duration<Rep1, Period>, Rep2>::type |
601 | >::type |
602 | operator/(const duration<Rep1, Period>& d, const Rep2& s) |
603 | { |
604 | typedef typename common_type<Rep1, Rep2>::type CR; |
605 | typedef duration<CR, Period> CD; |
606 | |
607 | return CD(CD(d).count()/static_cast<CR>(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 CD; |
617 | return CD(lhs).count() / CD(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 CR; |
630 | typedef duration<CR, Period> CD; |
631 | |
632 | return static_cast<CR>(s)/CD(d).count(); |
633 | } |
634 | #endif |
635 | // Duration % |
636 | |
637 | template <class Rep1, class Period, class Rep2> |
638 | inline BOOST_CONSTEXPR |
639 | typename boost::disable_if <boost::chrono::detail::is_duration<Rep2>, |
640 | typename boost::chrono::detail::duration_modulo_result< |
641 | duration<Rep1, Period>, Rep2>::type |
642 | >::type |
643 | operator%(const duration<Rep1, Period>& d, const Rep2& s) |
644 | { |
645 | typedef typename common_type<Rep1, Rep2>::type CR; |
646 | typedef duration<CR, Period> CD; |
647 | |
648 | return CD(CD(d).count()%static_cast<CR>(s)); |
649 | } |
650 | |
651 | template <class Rep1, class Period1, class Rep2, class Period2> |
652 | inline BOOST_CONSTEXPR |
653 | typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type |
654 | operator%(const duration<Rep1, Period1>& lhs, |
655 | const duration<Rep2, Period2>& rhs) { |
656 | typedef typename common_type<duration<Rep1, Period1>, |
657 | duration<Rep2, Period2> >::type CD; |
658 | |
659 | return CD(CD(lhs).count()%CD(rhs).count()); |
660 | } |
661 | |
662 | |
663 | //----------------------------------------------------------------------------// |
664 | // 20.9.3.6 duration comparisons [time.duration.comparisons] // |
665 | //----------------------------------------------------------------------------// |
666 | |
667 | namespace detail |
668 | { |
669 | template <class LhsDuration, class RhsDuration> |
670 | struct duration_eq |
671 | { |
672 | BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) const |
673 | { |
674 | typedef typename common_type<LhsDuration, RhsDuration>::type CD; |
675 | return CD(lhs).count() == CD(rhs).count(); |
676 | } |
677 | }; |
678 | |
679 | template <class LhsDuration> |
680 | struct duration_eq<LhsDuration, LhsDuration> |
681 | { |
682 | BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) const |
683 | { |
684 | return lhs.count() == rhs.count(); |
685 | } |
686 | }; |
687 | |
688 | template <class LhsDuration, class RhsDuration> |
689 | struct duration_lt |
690 | { |
691 | BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) const |
692 | { |
693 | typedef typename common_type<LhsDuration, RhsDuration>::type CD; |
694 | return CD(lhs).count() < CD(rhs).count(); |
695 | } |
696 | }; |
697 | |
698 | template <class LhsDuration> |
699 | struct duration_lt<LhsDuration, LhsDuration> |
700 | { |
701 | BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) const |
702 | { |
703 | return lhs.count() < rhs.count(); |
704 | } |
705 | }; |
706 | |
707 | } // namespace detail |
708 | |
709 | // Duration == |
710 | |
711 | template <class Rep1, class Period1, class Rep2, class Period2> |
712 | inline BOOST_CONSTEXPR |
713 | bool |
714 | operator==(const duration<Rep1, Period1>& lhs, |
715 | const duration<Rep2, Period2>& rhs) |
716 | { |
717 | return boost::chrono::detail::duration_eq< |
718 | duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs); |
719 | } |
720 | |
721 | // Duration != |
722 | |
723 | template <class Rep1, class Period1, class Rep2, class Period2> |
724 | inline BOOST_CONSTEXPR |
725 | bool |
726 | operator!=(const duration<Rep1, Period1>& lhs, |
727 | const duration<Rep2, Period2>& rhs) |
728 | { |
729 | return !(lhs == rhs); |
730 | } |
731 | |
732 | // Duration < |
733 | |
734 | template <class Rep1, class Period1, class Rep2, class Period2> |
735 | inline BOOST_CONSTEXPR |
736 | bool |
737 | operator< (const duration<Rep1, Period1>& lhs, |
738 | const duration<Rep2, Period2>& rhs) |
739 | { |
740 | return boost::chrono::detail::duration_lt< |
741 | duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs); |
742 | } |
743 | |
744 | // Duration > |
745 | |
746 | template <class Rep1, class Period1, class Rep2, class Period2> |
747 | inline BOOST_CONSTEXPR |
748 | bool |
749 | operator> (const duration<Rep1, Period1>& lhs, |
750 | const duration<Rep2, Period2>& rhs) |
751 | { |
752 | return rhs < lhs; |
753 | } |
754 | |
755 | // Duration <= |
756 | |
757 | template <class Rep1, class Period1, class Rep2, class Period2> |
758 | inline BOOST_CONSTEXPR |
759 | bool |
760 | operator<=(const duration<Rep1, Period1>& lhs, |
761 | const duration<Rep2, Period2>& rhs) |
762 | { |
763 | return !(rhs < lhs); |
764 | } |
765 | |
766 | // Duration >= |
767 | |
768 | template <class Rep1, class Period1, class Rep2, class Period2> |
769 | inline BOOST_CONSTEXPR |
770 | bool |
771 | operator>=(const duration<Rep1, Period1>& lhs, |
772 | const duration<Rep2, Period2>& rhs) |
773 | { |
774 | return !(lhs < rhs); |
775 | } |
776 | |
777 | //----------------------------------------------------------------------------// |
778 | // 20.9.3.7 duration_cast [time.duration.cast] // |
779 | //----------------------------------------------------------------------------// |
780 | |
781 | // Compile-time select the most efficient algorithm for the conversion... |
782 | template <class ToDuration, class Rep, class Period> |
783 | inline BOOST_CONSTEXPR |
784 | typename boost::enable_if < |
785 | boost::chrono::detail::is_duration<ToDuration>, ToDuration>::type |
786 | duration_cast(const duration<Rep, Period>& fd) |
787 | { |
788 | return boost::chrono::detail::duration_cast< |
789 | duration<Rep, Period>, ToDuration>()(fd); |
790 | } |
791 | |
792 | } // namespace chrono |
793 | } // namespace boost |
794 | |
795 | #ifndef BOOST_CHRONO_HEADER_ONLY |
796 | // the suffix header occurs after all of our code: |
797 | #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas |
798 | #endif |
799 | |
800 | #endif // BOOST_CHRONO_DURATION_HPP |
801 | |