]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 : rep_() {}; | |
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 |