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