]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/units/include/boost/units/quantity.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / units / include / boost / units / quantity.hpp
1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and
2 // unit/quantity manipulation and conversion
3 //
4 // Copyright (C) 2003-2008 Matthias Christian Schabel
5 // Copyright (C) 2007-2008 Steven Watanabe
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See
8 // accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10
11 #ifndef BOOST_UNITS_QUANTITY_HPP
12 #define BOOST_UNITS_QUANTITY_HPP
13
14 #include <algorithm>
15
16 #include <boost/config.hpp>
17 #include <boost/static_assert.hpp>
18 #include <boost/mpl/bool.hpp>
19 #include <boost/mpl/and.hpp>
20 #include <boost/mpl/not.hpp>
21 #include <boost/mpl/or.hpp>
22 #include <boost/mpl/assert.hpp>
23 #include <boost/utility/enable_if.hpp>
24 #include <boost/type_traits/is_arithmetic.hpp>
25 #include <boost/type_traits/is_convertible.hpp>
26 #include <boost/type_traits/is_integral.hpp>
27 #include <boost/type_traits/is_same.hpp>
28
29 #include <boost/units/conversion.hpp>
30 #include <boost/units/dimensionless_type.hpp>
31 #include <boost/units/homogeneous_system.hpp>
32 #include <boost/units/operators.hpp>
33 #include <boost/units/static_rational.hpp>
34 #include <boost/units/units_fwd.hpp>
35 #include <boost/units/detail/dimensionless_unit.hpp>
36
37 namespace boost {
38
39 namespace units {
40
41 namespace detail {
42
43 template<class T, class Enable = void>
44 struct is_base_unit : mpl::false_ {};
45
46 template<class T>
47 struct is_base_unit<T, typename T::boost_units_is_base_unit_type> : mpl::true_ {};
48
49 template<class Source, class Destination>
50 struct is_narrowing_conversion_impl : mpl::bool_<(sizeof(Source) > sizeof(Destination))> {};
51
52 template<class Source, class Destination>
53 struct is_non_narrowing_conversion :
54 mpl::and_<
55 boost::is_convertible<Source, Destination>,
56 mpl::not_<
57 mpl::and_<
58 boost::is_arithmetic<Source>,
59 boost::is_arithmetic<Destination>,
60 mpl::or_<
61 mpl::and_<
62 is_integral<Destination>,
63 mpl::not_<is_integral<Source> >
64 >,
65 is_narrowing_conversion_impl<Source, Destination>
66 >
67 >
68 >
69 >
70 {};
71
72 template<>
73 struct is_non_narrowing_conversion<long double, double> : mpl::false_ {};
74
75 // msvc 7.1 needs extra disambiguation
76 template<class T, class U>
77 struct disable_if_is_same
78 {
79 typedef void type;
80 };
81
82 template<class T>
83 struct disable_if_is_same<T, T> {};
84
85 }
86
87 /// class declaration
88 template<class Unit,class Y>
89 class quantity
90 {
91 // base units are not the same as units.
92 BOOST_MPL_ASSERT_NOT((detail::is_base_unit<Unit>));
93 enum { force_instantiation_of_unit = sizeof(Unit) };
94 typedef void (quantity::*unspecified_null_pointer_constant_type)(int*******);
95 public:
96 typedef quantity<Unit,Y> this_type;
97
98 typedef Y value_type;
99 typedef Unit unit_type;
100
101 quantity() : val_()
102 {
103 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
104 }
105
106 quantity(unspecified_null_pointer_constant_type) : val_()
107 {
108 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
109 }
110
111 quantity(const this_type& source) : val_(source.val_)
112 {
113 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
114 }
115
116 // Need to make sure that the destructor of
117 // Unit which contains the checking is instantiated,
118 // on sun.
119 #ifdef __SUNPRO_CC
120 ~quantity() {
121 unit_type force_unit_instantiation;
122 }
123 #endif
124
125 //~quantity() { }
126
127 this_type& operator=(const this_type& source)
128 {
129 val_ = source.val_;
130
131 return *this;
132 }
133
134 #ifndef BOOST_NO_SFINAE
135
136 /// implicit conversion between value types is allowed if allowed for value types themselves
137 template<class YY>
138 quantity(const quantity<Unit,YY>& source,
139 typename boost::enable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
140 val_(source.value())
141 {
142 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
143 }
144
145 /// implicit conversion between value types is not allowed if not allowed for value types themselves
146 template<class YY>
147 explicit quantity(const quantity<Unit,YY>& source,
148 typename boost::disable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
149 val_(static_cast<Y>(source.value()))
150 {
151 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
152 }
153
154 #else
155
156 /// implicit conversion between value types is allowed if allowed for value types themselves
157 template<class YY>
158 quantity(const quantity<Unit,YY>& source) :
159 val_(source.value())
160 {
161 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
162 BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
163 }
164
165 #endif
166
167 /// implicit assignment between value types is allowed if allowed for value types themselves
168 template<class YY>
169 this_type& operator=(const quantity<Unit,YY>& source)
170 {
171 BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
172
173 *this = this_type(source);
174
175 return *this;
176 }
177
178 #ifndef BOOST_NO_SFINAE
179
180 /// explicit conversion between different unit systems is allowed if implicit conversion is disallowed
181 template<class Unit2,class YY>
182 explicit
183 quantity(const quantity<Unit2,YY>& source,
184 typename boost::disable_if<
185 mpl::and_<
186 //is_implicitly_convertible should be undefined when the
187 //units are not convertible at all
188 typename is_implicitly_convertible<Unit2,Unit>::type,
189 detail::is_non_narrowing_conversion<YY, Y>
190 >,
191 typename detail::disable_if_is_same<Unit, Unit2>::type
192 >::type* = 0)
193 : val_(conversion_helper<quantity<Unit2,YY>,this_type>::convert(source).value())
194 {
195 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
196 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
197 }
198
199 /// implicit conversion between different unit systems is allowed if each fundamental dimension is implicitly convertible
200 template<class Unit2,class YY>
201 quantity(const quantity<Unit2,YY>& source,
202 typename boost::enable_if<
203 mpl::and_<
204 typename is_implicitly_convertible<Unit2,Unit>::type,
205 detail::is_non_narrowing_conversion<YY, Y>
206 >,
207 typename detail::disable_if_is_same<Unit, Unit2>::type
208 >::type* = 0)
209 : val_(conversion_helper<quantity<Unit2,YY>,this_type>::convert(source).value())
210 {
211 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
212 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
213 }
214
215 #else
216
217 /// without SFINAE we can't distinguish between explicit and implicit conversions so
218 /// the conversion is always explicit
219 template<class Unit2,class YY>
220 explicit quantity(const quantity<Unit2,YY>& source)
221 : val_(conversion_helper<quantity<Unit2,YY>,this_type>::convert(source).value())
222 {
223 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
224 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
225 }
226
227 #endif
228
229 /// implicit assignment between different unit systems is allowed if each fundamental dimension is implicitly convertible
230 template<class Unit2,class YY>
231 this_type& operator=(const quantity<Unit2,YY>& source)
232 {
233
234 BOOST_STATIC_ASSERT((is_implicitly_convertible<Unit2,unit_type>::value == true));
235 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
236
237 *this = this_type(source);
238
239 return *this;
240 }
241
242 const value_type& value() const { return val_; } ///< constant accessor to value
243
244 ///< can add a quantity of the same type if add_typeof_helper<value_type,value_type>::type is convertible to value_type
245 template<class Unit2, class YY>
246 this_type& operator+=(const quantity<Unit2, YY>& source)
247 {
248 BOOST_STATIC_ASSERT((boost::is_same<typename add_typeof_helper<Unit, Unit2>::type, Unit>::value));
249 val_ += source.value();
250 return *this;
251 }
252
253 ///< can subtract a quantity of the same type if subtract_typeof_helper<value_type,value_type>::type is convertible to value_type
254 template<class Unit2, class YY>
255 this_type& operator-=(const quantity<Unit2, YY>& source)
256 {
257 BOOST_STATIC_ASSERT((boost::is_same<typename subtract_typeof_helper<Unit, Unit2>::type, Unit>::value));
258 val_ -= source.value();
259 return *this;
260 }
261
262 template<class Unit2, class YY>
263 this_type& operator*=(const quantity<Unit2, YY>& source)
264 {
265 BOOST_STATIC_ASSERT((boost::is_same<typename multiply_typeof_helper<Unit, Unit2>::type, Unit>::value));
266 val_ *= source.value();
267 return *this;
268 }
269
270 template<class Unit2, class YY>
271 this_type& operator/=(const quantity<Unit2, YY>& source)
272 {
273 BOOST_STATIC_ASSERT((boost::is_same<typename divide_typeof_helper<Unit, Unit2>::type, Unit>::value));
274 val_ /= source.value();
275 return *this;
276 }
277
278 ///< can multiply a quantity by a scalar value_type if multiply_typeof_helper<value_type,value_type>::type is convertible to value_type
279 this_type& operator*=(const value_type& source) { val_ *= source; return *this; }
280 ///< can divide a quantity by a scalar value_type if divide_typeof_helper<value_type,value_type>::type is convertible to value_type
281 this_type& operator/=(const value_type& source) { val_ /= source; return *this; }
282
283 /// Construct quantity directly from @c value_type (potentially dangerous).
284 static this_type from_value(const value_type& val) { return this_type(val, 0); }
285
286 protected:
287 explicit quantity(const value_type& val, int) : val_(val) { }
288
289 private:
290 value_type val_;
291 };
292
293 /// Specialization for dimensionless quantities. Implicit conversions between
294 /// unit systems are allowed because all dimensionless quantities are equivalent.
295 /// Implicit construction and assignment from and conversion to @c value_type is
296 /// also allowed.
297 template<class System,class Y>
298 class quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(System),Y>
299 {
300 public:
301 typedef quantity<unit<dimensionless_type,System>,Y> this_type;
302
303 typedef Y value_type;
304 typedef System system_type;
305 typedef dimensionless_type dimension_type;
306 typedef unit<dimension_type,system_type> unit_type;
307
308 quantity() : val_()
309 {
310 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
311 }
312
313 /// construction from raw @c value_type is allowed
314 quantity(value_type val) : val_(val)
315 {
316 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
317 }
318
319 quantity(const this_type& source) : val_(source.val_)
320 {
321 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
322 }
323
324 //~quantity() { }
325
326 this_type& operator=(const this_type& source)
327 {
328 val_ = source.val_;
329
330 return *this;
331 }
332
333 #ifndef BOOST_NO_SFINAE
334
335 /// implicit conversion between value types is allowed if allowed for value types themselves
336 template<class YY>
337 quantity(const quantity<unit<dimension_type,system_type>,YY>& source,
338 typename boost::enable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
339 val_(source.value())
340 {
341 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
342 }
343
344 /// implicit conversion between value types is not allowed if not allowed for value types themselves
345 template<class YY>
346 explicit quantity(const quantity<unit<dimension_type,system_type>,YY>& source,
347 typename boost::disable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
348 val_(static_cast<Y>(source.value()))
349 {
350 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
351 }
352
353 #else
354
355 /// implicit conversion between value types is allowed if allowed for value types themselves
356 template<class YY>
357 quantity(const quantity<unit<dimension_type,system_type>,YY>& source) :
358 val_(source.value())
359 {
360 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
361 BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
362 }
363
364 #endif
365
366 /// implicit assignment between value types is allowed if allowed for value types themselves
367 template<class YY>
368 this_type& operator=(const quantity<unit<dimension_type,system_type>,YY>& source)
369 {
370 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
371
372 *this = this_type(source);
373
374 return *this;
375 }
376
377 #if 1
378
379 /// implicit conversion between different unit systems is allowed
380 template<class System2, class Y2>
381 quantity(const quantity<unit<dimensionless_type, System2>,Y2>& source,
382 #ifdef __SUNPRO_CC
383 typename boost::enable_if<
384 boost::mpl::and_<
385 detail::is_non_narrowing_conversion<Y2, Y>,
386 detail::is_dimensionless_system<System2>
387 >
388 >::type* = 0
389 #else
390 typename boost::enable_if<detail::is_non_narrowing_conversion<Y2, Y> >::type* = 0,
391 typename detail::disable_if_is_same<System, System2>::type* = 0,
392 typename boost::enable_if<detail::is_dimensionless_system<System2> >::type* = 0
393 #endif
394 ) :
395 val_(source.value())
396 {
397 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
398 }
399
400 /// implicit conversion between different unit systems is allowed
401 template<class System2, class Y2>
402 explicit quantity(const quantity<unit<dimensionless_type, System2>,Y2>& source,
403 #ifdef __SUNPRO_CC
404 typename boost::enable_if<
405 boost::mpl::and_<
406 boost::mpl::not_<detail::is_non_narrowing_conversion<Y2, Y> >,
407 detail::is_dimensionless_system<System2>
408 >
409 >::type* = 0
410 #else
411 typename boost::disable_if<detail::is_non_narrowing_conversion<Y2, Y> >::type* = 0,
412 typename detail::disable_if_is_same<System, System2>::type* = 0,
413 typename boost::enable_if<detail::is_dimensionless_system<System2> >::type* = 0
414 #endif
415 ) :
416 val_(static_cast<Y>(source.value()))
417 {
418 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
419 }
420
421 #else
422
423 /// implicit conversion between different unit systems is allowed
424 template<class System2, class Y2>
425 quantity(const quantity<unit<dimensionless_type,homogeneous_system<System2> >,Y2>& source) :
426 val_(source.value())
427 {
428 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
429 BOOST_STATIC_ASSERT((boost::is_convertible<Y2, Y>::value == true));
430 }
431
432 #endif
433
434 /// conversion between different unit systems is explicit when
435 /// the units are not equivalent.
436 template<class System2, class Y2>
437 explicit quantity(const quantity<unit<dimensionless_type, System2>,Y2>& source,
438 typename boost::disable_if<detail::is_dimensionless_system<System2> >::type* = 0) :
439 val_(conversion_helper<quantity<unit<dimensionless_type, System2>,Y2>, this_type>::convert(source).value())
440 {
441 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
442 }
443
444 #ifndef __SUNPRO_CC
445
446 /// implicit assignment between different unit systems is allowed
447 template<class System2>
448 this_type& operator=(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(System2),Y>& source)
449 {
450 *this = this_type(source);
451
452 return *this;
453 }
454
455 #endif
456
457 /// implicit conversion to @c value_type is allowed
458 operator value_type() const { return val_; }
459
460 const value_type& value() const { return val_; } ///< constant accessor to value
461
462 ///< can add a quantity of the same type if add_typeof_helper<value_type,value_type>::type is convertible to value_type
463 this_type& operator+=(const this_type& source) { val_ += source.val_; return *this; }
464
465 ///< can subtract a quantity of the same type if subtract_typeof_helper<value_type,value_type>::type is convertible to value_type
466 this_type& operator-=(const this_type& source) { val_ -= source.val_; return *this; }
467
468 ///< can multiply a quantity by a scalar value_type if multiply_typeof_helper<value_type,value_type>::type is convertible to value_type
469 this_type& operator*=(const value_type& val) { val_ *= val; return *this; }
470
471 ///< can divide a quantity by a scalar value_type if divide_typeof_helper<value_type,value_type>::type is convertible to value_type
472 this_type& operator/=(const value_type& val) { val_ /= val; return *this; }
473
474 /// Construct quantity directly from @c value_type.
475 static this_type from_value(const value_type& val) { return this_type(val); }
476
477 private:
478 value_type val_;
479 };
480
481 #ifdef BOOST_MSVC
482 // HACK: For some obscure reason msvc 8.0 needs these specializations
483 template<class System, class T>
484 class quantity<unit<int, System>, T> {};
485 template<class T>
486 class quantity<int, T> {};
487 #endif
488
489 } // namespace units
490
491 } // namespace boost
492
493 #if BOOST_UNITS_HAS_BOOST_TYPEOF
494
495 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
496
497 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::quantity, 2)
498
499 #endif
500
501 namespace boost {
502
503 namespace units {
504
505 namespace detail {
506
507 /// helper class for quantity_cast
508 template<class X,class Y> struct quantity_cast_helper;
509
510 /// specialization for casting to the value type
511 template<class Y,class X,class Unit>
512 struct quantity_cast_helper<Y,quantity<Unit,X> >
513 {
514 typedef Y type;
515
516 type operator()(quantity<Unit,X>& source) { return const_cast<X&>(source.value()); }
517 };
518
519 /// specialization for casting to the value type
520 template<class Y,class X,class Unit>
521 struct quantity_cast_helper<Y,const quantity<Unit,X> >
522 {
523 typedef Y type;
524
525 type operator()(const quantity<Unit,X>& source) { return source.value(); }
526 };
527
528 } // namespace detail
529
530 /// quantity_cast provides mutating access to underlying quantity value_type
531 template<class X,class Y>
532 inline
533 X
534 quantity_cast(Y& source)
535 {
536 detail::quantity_cast_helper<X,Y> qch;
537
538 return qch(source);
539 }
540
541 template<class X,class Y>
542 inline
543 X
544 quantity_cast(const Y& source)
545 {
546 detail::quantity_cast_helper<X,const Y> qch;
547
548 return qch(source);
549 }
550
551 /// swap quantities
552 template<class Unit,class Y>
553 inline void swap(quantity<Unit,Y>& lhs, quantity<Unit,Y>& rhs)
554 {
555 using std::swap;
556 swap(quantity_cast<Y&>(lhs),quantity_cast<Y&>(rhs));
557 }
558
559 /// specialize unary plus typeof helper
560 /// INTERNAL ONLY
561 template<class Unit,class Y>
562 struct unary_plus_typeof_helper< quantity<Unit,Y> >
563 {
564 typedef typename unary_plus_typeof_helper<Y>::type value_type;
565 typedef typename unary_plus_typeof_helper<Unit>::type unit_type;
566 typedef quantity<unit_type,value_type> type;
567 };
568
569 /// specialize unary minus typeof helper
570 /// INTERNAL ONLY
571 template<class Unit,class Y>
572 struct unary_minus_typeof_helper< quantity<Unit,Y> >
573 {
574 typedef typename unary_minus_typeof_helper<Y>::type value_type;
575 typedef typename unary_minus_typeof_helper<Unit>::type unit_type;
576 typedef quantity<unit_type,value_type> type;
577 };
578
579 /// specialize add typeof helper
580 /// INTERNAL ONLY
581 template<class Unit1,
582 class Unit2,
583 class X,
584 class Y>
585 struct add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
586 {
587 typedef typename add_typeof_helper<X,Y>::type value_type;
588 typedef typename add_typeof_helper<Unit1,Unit2>::type unit_type;
589 typedef quantity<unit_type,value_type> type;
590 };
591
592 /// for sun CC we need to invoke SFINAE at
593 /// the top level, otherwise it will silently
594 /// return int.
595 template<class Dim1, class System1,
596 class Dim2, class System2,
597 class X,
598 class Y>
599 struct add_typeof_helper< quantity<unit<Dim1, System1>,X>,quantity<unit<Dim2, System2>,Y> >
600 {
601 };
602
603 template<class Dim,
604 class System,
605 class X,
606 class Y>
607 struct add_typeof_helper< quantity<unit<Dim, System>,X>,quantity<unit<Dim, System>,Y> >
608 {
609 typedef typename add_typeof_helper<X,Y>::type value_type;
610 typedef unit<Dim, System> unit_type;
611 typedef quantity<unit_type,value_type> type;
612 };
613
614 /// specialize subtract typeof helper
615 /// INTERNAL ONLY
616 template<class Unit1,
617 class Unit2,
618 class X,
619 class Y>
620 struct subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
621 {
622 typedef typename subtract_typeof_helper<X,Y>::type value_type;
623 typedef typename subtract_typeof_helper<Unit1,Unit2>::type unit_type;
624 typedef quantity<unit_type,value_type> type;
625 };
626
627 // Force adding different units to fail on sun.
628 template<class Dim1, class System1,
629 class Dim2, class System2,
630 class X,
631 class Y>
632 struct subtract_typeof_helper< quantity<unit<Dim1, System1>,X>,quantity<unit<Dim2, System2>,Y> >
633 {
634 };
635
636 template<class Dim,
637 class System,
638 class X,
639 class Y>
640 struct subtract_typeof_helper< quantity<unit<Dim, System>,X>,quantity<unit<Dim, System>,Y> >
641 {
642 typedef typename subtract_typeof_helper<X,Y>::type value_type;
643 typedef unit<Dim, System> unit_type;
644 typedef quantity<unit_type,value_type> type;
645 };
646
647 /// scalar times unit typeof helper
648 /// INTERNAL ONLY
649 template<class System,
650 class Dim,
651 class X>
652 struct multiply_typeof_helper< X,unit<Dim,System> >
653 {
654 typedef X value_type;
655 typedef unit<Dim,System> unit_type;
656 typedef quantity<unit_type,value_type> type;
657 };
658
659 /// unit times scalar typeof helper
660 /// INTERNAL ONLY
661 template<class System,
662 class Dim,
663 class X>
664 struct multiply_typeof_helper< unit<Dim,System>,X >
665 {
666 typedef X value_type;
667 typedef unit<Dim,System> unit_type;
668 typedef quantity<unit_type,value_type> type;
669 };
670
671 /// scalar times quantity typeof helper
672 /// INTERNAL ONLY
673 template<class Unit,
674 class X,
675 class Y>
676 struct multiply_typeof_helper< X,quantity<Unit,Y> >
677 {
678 typedef typename multiply_typeof_helper<X,Y>::type value_type;
679 typedef Unit unit_type;
680 typedef quantity<unit_type,value_type> type;
681 };
682
683 /// disambiguate
684 /// INTERNAL ONLY
685 template<class Unit,
686 class Y>
687 struct multiply_typeof_helper< one,quantity<Unit,Y> >
688 {
689 typedef quantity<Unit,Y> type;
690 };
691
692 /// quantity times scalar typeof helper
693 /// INTERNAL ONLY
694 template<class Unit,
695 class X,
696 class Y>
697 struct multiply_typeof_helper< quantity<Unit,X>,Y >
698 {
699 typedef typename multiply_typeof_helper<X,Y>::type value_type;
700 typedef Unit unit_type;
701 typedef quantity<unit_type,value_type> type;
702 };
703
704 /// disambiguate
705 /// INTERNAL ONLY
706 template<class Unit,
707 class X>
708 struct multiply_typeof_helper< quantity<Unit,X>,one >
709 {
710 typedef quantity<Unit,X> type;
711 };
712
713 /// unit times quantity typeof helper
714 /// INTERNAL ONLY
715 template<class Unit,
716 class System,
717 class Dim,
718 class X>
719 struct multiply_typeof_helper< unit<Dim,System>,quantity<Unit,X> >
720 {
721 typedef X value_type;
722 typedef typename multiply_typeof_helper< unit<Dim,System>,Unit >::type unit_type;
723 typedef quantity<unit_type,value_type> type;
724 };
725
726 /// quantity times unit typeof helper
727 /// INTERNAL ONLY
728 template<class Unit,
729 class System,
730 class Dim,
731 class X>
732 struct multiply_typeof_helper< quantity<Unit,X>,unit<Dim,System> >
733 {
734 typedef X value_type;
735 typedef typename multiply_typeof_helper< Unit,unit<Dim,System> >::type unit_type;
736 typedef quantity<unit_type,value_type> type;
737 };
738
739 /// quantity times quantity typeof helper
740 /// INTERNAL ONLY
741 template<class Unit1,
742 class Unit2,
743 class X,
744 class Y>
745 struct multiply_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
746 {
747 typedef typename multiply_typeof_helper<X,Y>::type value_type;
748 typedef typename multiply_typeof_helper<Unit1,Unit2>::type unit_type;
749 typedef quantity<unit_type,value_type> type;
750 };
751
752 /// scalar divided by unit typeof helper
753 /// INTERNAL ONLY
754 template<class System,
755 class Dim,
756 class X>
757 struct divide_typeof_helper< X,unit<Dim,System> >
758 {
759 typedef X value_type;
760 typedef typename power_typeof_helper< unit<Dim,System>,static_rational<-1> >::type unit_type;
761 typedef quantity<unit_type,value_type> type;
762 };
763
764 /// unit divided by scalar typeof helper
765 /// INTERNAL ONLY
766 template<class System,
767 class Dim,
768 class X>
769 struct divide_typeof_helper< unit<Dim,System>,X >
770 {
771 typedef typename divide_typeof_helper<X,X>::type value_type;
772 typedef unit<Dim,System> unit_type;
773 typedef quantity<unit_type,value_type> type;
774 };
775
776 /// scalar divided by quantity typeof helper
777 /// INTERNAL ONLY
778 template<class Unit,
779 class X,
780 class Y>
781 struct divide_typeof_helper< X,quantity<Unit,Y> >
782 {
783 typedef typename divide_typeof_helper<X,Y>::type value_type;
784 typedef typename power_typeof_helper< Unit,static_rational<-1> >::type unit_type;
785 typedef quantity<unit_type,value_type> type;
786 };
787
788 /// disambiguate
789 /// INTERNAL ONLY
790 template<class Unit,
791 class Y>
792 struct divide_typeof_helper< one,quantity<Unit,Y> >
793 {
794 typedef quantity<Unit,Y> type;
795 };
796
797 /// quantity divided by scalar typeof helper
798 /// INTERNAL ONLY
799 template<class Unit,
800 class X,
801 class Y>
802 struct divide_typeof_helper< quantity<Unit,X>,Y >
803 {
804 typedef typename divide_typeof_helper<X,Y>::type value_type;
805 typedef Unit unit_type;
806 typedef quantity<unit_type,value_type> type;
807 };
808
809 /// disambiguate
810 /// INTERNAL ONLY
811 template<class Unit,
812 class X>
813 struct divide_typeof_helper< quantity<Unit,X>,one >
814 {
815 typedef quantity<Unit,X> type;
816 };
817
818 /// unit divided by quantity typeof helper
819 /// INTERNAL ONLY
820 template<class Unit,
821 class System,
822 class Dim,
823 class X>
824 struct divide_typeof_helper< unit<Dim,System>,quantity<Unit,X> >
825 {
826 typedef typename divide_typeof_helper<X,X>::type value_type;
827 typedef typename divide_typeof_helper< unit<Dim,System>,Unit >::type unit_type;
828 typedef quantity<unit_type,value_type> type;
829 };
830
831 /// quantity divided by unit typeof helper
832 /// INTERNAL ONLY
833 template<class Unit,
834 class System,
835 class Dim,
836 class X>
837 struct divide_typeof_helper< quantity<Unit,X>,unit<Dim,System> >
838 {
839 typedef X value_type;
840 typedef typename divide_typeof_helper< Unit,unit<Dim,System> >::type unit_type;
841 typedef quantity<unit_type,value_type> type;
842 };
843
844 /// quantity divided by quantity typeof helper
845 /// INTERNAL ONLY
846 template<class Unit1,
847 class Unit2,
848 class X,
849 class Y>
850 struct divide_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
851 {
852 typedef typename divide_typeof_helper<X,Y>::type value_type;
853 typedef typename divide_typeof_helper<Unit1,Unit2>::type unit_type;
854 typedef quantity<unit_type,value_type> type;
855 };
856
857 /// specialize power typeof helper
858 /// INTERNAL ONLY
859 template<class Unit,long N,long D,class Y>
860 struct power_typeof_helper< quantity<Unit,Y>,static_rational<N,D> >
861 {
862 typedef typename power_typeof_helper<Y,static_rational<N,D> >::type value_type;
863 typedef typename power_typeof_helper<Unit,static_rational<N,D> >::type unit_type;
864 typedef quantity<unit_type,value_type> type;
865
866 static type value(const quantity<Unit,Y>& x)
867 {
868 return type::from_value(power_typeof_helper<Y,static_rational<N,D> >::value(x.value()));
869 }
870 };
871
872 /// specialize root typeof helper
873 /// INTERNAL ONLY
874 template<class Unit,long N,long D,class Y>
875 struct root_typeof_helper< quantity<Unit,Y>,static_rational<N,D> >
876 {
877 typedef typename root_typeof_helper<Y,static_rational<N,D> >::type value_type;
878 typedef typename root_typeof_helper<Unit,static_rational<N,D> >::type unit_type;
879 typedef quantity<unit_type,value_type> type;
880
881 static type value(const quantity<Unit,Y>& x)
882 {
883 return type::from_value(root_typeof_helper<Y,static_rational<N,D> >::value(x.value()));
884 }
885 };
886
887 /// runtime unit times scalar
888 /// INTERNAL ONLY
889 template<class System,
890 class Dim,
891 class Y>
892 inline
893 typename multiply_typeof_helper< unit<Dim,System>,Y >::type
894 operator*(const unit<Dim,System>&,const Y& rhs)
895 {
896 typedef typename multiply_typeof_helper< unit<Dim,System>,Y >::type type;
897
898 return type::from_value(rhs);
899 }
900
901 /// runtime unit divided by scalar
902 template<class System,
903 class Dim,
904 class Y>
905 inline
906 typename divide_typeof_helper< unit<Dim,System>,Y >::type
907 operator/(const unit<Dim,System>&,const Y& rhs)
908 {
909 typedef typename divide_typeof_helper<unit<Dim,System>,Y>::type type;
910
911 return type::from_value(Y(1)/rhs);
912 }
913
914 /// runtime scalar times unit
915 template<class System,
916 class Dim,
917 class Y>
918 inline
919 typename multiply_typeof_helper< Y,unit<Dim,System> >::type
920 operator*(const Y& lhs,const unit<Dim,System>&)
921 {
922 typedef typename multiply_typeof_helper< Y,unit<Dim,System> >::type type;
923
924 return type::from_value(lhs);
925 }
926
927 /// runtime scalar divided by unit
928 template<class System,
929 class Dim,
930 class Y>
931 inline
932 typename divide_typeof_helper< Y,unit<Dim,System> >::type
933 operator/(const Y& lhs,const unit<Dim,System>&)
934 {
935 typedef typename divide_typeof_helper< Y,unit<Dim,System> >::type type;
936
937 return type::from_value(lhs);
938 }
939
940 ///// runtime quantity times scalar
941 //template<class Unit,
942 // class X,
943 // class Y>
944 //inline
945 //typename multiply_typeof_helper< quantity<Unit,X>,Y >::type
946 //operator*(const quantity<Unit,X>& lhs,const Y& rhs)
947 //{
948 // typedef typename multiply_typeof_helper< quantity<Unit,X>,Y >::type type;
949 //
950 // return type::from_value(lhs.value()*rhs);
951 //}
952 //
953 ///// runtime scalar times quantity
954 //template<class Unit,
955 // class X,
956 // class Y>
957 //inline
958 //typename multiply_typeof_helper< X,quantity<Unit,Y> >::type
959 //operator*(const X& lhs,const quantity<Unit,Y>& rhs)
960 //{
961 // typedef typename multiply_typeof_helper< X,quantity<Unit,Y> >::type type;
962 //
963 // return type::from_value(lhs*rhs.value());
964 //}
965
966 /// runtime quantity times scalar
967 template<class Unit,
968 class X>
969 inline
970 typename multiply_typeof_helper< quantity<Unit,X>,X >::type
971 operator*(const quantity<Unit,X>& lhs,const X& rhs)
972 {
973 typedef typename multiply_typeof_helper< quantity<Unit,X>,X >::type type;
974
975 return type::from_value(lhs.value()*rhs);
976 }
977
978 /// runtime scalar times quantity
979 template<class Unit,
980 class X>
981 inline
982 typename multiply_typeof_helper< X,quantity<Unit,X> >::type
983 operator*(const X& lhs,const quantity<Unit,X>& rhs)
984 {
985 typedef typename multiply_typeof_helper< X,quantity<Unit,X> >::type type;
986
987 return type::from_value(lhs*rhs.value());
988 }
989
990 ///// runtime quantity divided by scalar
991 //template<class Unit,
992 // class X,
993 // class Y>
994 //inline
995 //typename divide_typeof_helper< quantity<Unit,X>,Y >::type
996 //operator/(const quantity<Unit,X>& lhs,const Y& rhs)
997 //{
998 // typedef typename divide_typeof_helper< quantity<Unit,X>,Y >::type type;
999 //
1000 // return type::from_value(lhs.value()/rhs);
1001 //}
1002 //
1003 ///// runtime scalar divided by quantity
1004 //template<class Unit,
1005 // class X,
1006 // class Y>
1007 //inline
1008 //typename divide_typeof_helper< X,quantity<Unit,Y> >::type
1009 //operator/(const X& lhs,const quantity<Unit,Y>& rhs)
1010 //{
1011 // typedef typename divide_typeof_helper< X,quantity<Unit,Y> >::type type;
1012 //
1013 // return type::from_value(lhs/rhs.value());
1014 //}
1015
1016 /// runtime quantity divided by scalar
1017 template<class Unit,
1018 class X>
1019 inline
1020 typename divide_typeof_helper< quantity<Unit,X>,X >::type
1021 operator/(const quantity<Unit,X>& lhs,const X& rhs)
1022 {
1023 typedef typename divide_typeof_helper< quantity<Unit,X>,X >::type type;
1024
1025 return type::from_value(lhs.value()/rhs);
1026 }
1027
1028 /// runtime scalar divided by quantity
1029 template<class Unit,
1030 class X>
1031 inline
1032 typename divide_typeof_helper< X,quantity<Unit,X> >::type
1033 operator/(const X& lhs,const quantity<Unit,X>& rhs)
1034 {
1035 typedef typename divide_typeof_helper< X,quantity<Unit,X> >::type type;
1036
1037 return type::from_value(lhs/rhs.value());
1038 }
1039
1040 /// runtime unit times quantity
1041 template<class System1,
1042 class Dim1,
1043 class Unit2,
1044 class Y>
1045 inline
1046 typename multiply_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type
1047 operator*(const unit<Dim1,System1>&,const quantity<Unit2,Y>& rhs)
1048 {
1049 typedef typename multiply_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type type;
1050
1051 return type::from_value(rhs.value());
1052 }
1053
1054 /// runtime unit divided by quantity
1055 template<class System1,
1056 class Dim1,
1057 class Unit2,
1058 class Y>
1059 inline
1060 typename divide_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type
1061 operator/(const unit<Dim1,System1>&,const quantity<Unit2,Y>& rhs)
1062 {
1063 typedef typename divide_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type type;
1064
1065 return type::from_value(Y(1)/rhs.value());
1066 }
1067
1068 /// runtime quantity times unit
1069 template<class Unit1,
1070 class System2,
1071 class Dim2,
1072 class Y>
1073 inline
1074 typename multiply_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type
1075 operator*(const quantity<Unit1,Y>& lhs,const unit<Dim2,System2>&)
1076 {
1077 typedef typename multiply_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type type;
1078
1079 return type::from_value(lhs.value());
1080 }
1081
1082 /// runtime quantity divided by unit
1083 template<class Unit1,
1084 class System2,
1085 class Dim2,
1086 class Y>
1087 inline
1088 typename divide_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type
1089 operator/(const quantity<Unit1,Y>& lhs,const unit<Dim2,System2>&)
1090 {
1091 typedef typename divide_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type type;
1092
1093 return type::from_value(lhs.value());
1094 }
1095
1096 /// runtime unary plus quantity
1097 template<class Unit,class Y>
1098 typename unary_plus_typeof_helper< quantity<Unit,Y> >::type
1099 operator+(const quantity<Unit,Y>& val)
1100 {
1101 typedef typename unary_plus_typeof_helper< quantity<Unit,Y> >::type type;
1102
1103 return type::from_value(+val.value());
1104 }
1105
1106 /// runtime unary minus quantity
1107 template<class Unit,class Y>
1108 typename unary_minus_typeof_helper< quantity<Unit,Y> >::type
1109 operator-(const quantity<Unit,Y>& val)
1110 {
1111 typedef typename unary_minus_typeof_helper< quantity<Unit,Y> >::type type;
1112
1113 return type::from_value(-val.value());
1114 }
1115
1116 /// runtime quantity plus quantity
1117 template<class Unit1,
1118 class Unit2,
1119 class X,
1120 class Y>
1121 inline
1122 typename add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1123 operator+(const quantity<Unit1,X>& lhs,
1124 const quantity<Unit2,Y>& rhs)
1125 {
1126 typedef typename add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type type;
1127
1128 return type::from_value(lhs.value()+rhs.value());
1129 }
1130
1131 /// runtime quantity minus quantity
1132 template<class Unit1,
1133 class Unit2,
1134 class X,
1135 class Y>
1136 inline
1137 typename subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1138 operator-(const quantity<Unit1,X>& lhs,
1139 const quantity<Unit2,Y>& rhs)
1140 {
1141 typedef typename subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type type;
1142
1143 return type::from_value(lhs.value()-rhs.value());
1144 }
1145
1146 /// runtime quantity times quantity
1147 template<class Unit1,
1148 class Unit2,
1149 class X,
1150 class Y>
1151 inline
1152 typename multiply_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1153 operator*(const quantity<Unit1,X>& lhs,
1154 const quantity<Unit2,Y>& rhs)
1155 {
1156 typedef typename multiply_typeof_helper< quantity<Unit1,X>,
1157 quantity<Unit2,Y> >::type type;
1158
1159 return type::from_value(lhs.value()*rhs.value());
1160 }
1161
1162 /// runtime quantity divided by quantity
1163 template<class Unit1,
1164 class Unit2,
1165 class X,
1166 class Y>
1167 inline
1168 typename divide_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1169 operator/(const quantity<Unit1,X>& lhs,
1170 const quantity<Unit2,Y>& rhs)
1171 {
1172 typedef typename divide_typeof_helper< quantity<Unit1,X>,
1173 quantity<Unit2,Y> >::type type;
1174
1175 return type::from_value(lhs.value()/rhs.value());
1176 }
1177
1178 /// runtime operator==
1179 template<class Unit,
1180 class X,
1181 class Y>
1182 inline
1183 bool
1184 operator==(const quantity<Unit,X>& val1,
1185 const quantity<Unit,Y>& val2)
1186 {
1187 return val1.value() == val2.value();
1188 }
1189
1190 /// runtime operator!=
1191 template<class Unit,
1192 class X,
1193 class Y>
1194 inline
1195 bool
1196 operator!=(const quantity<Unit,X>& val1,
1197 const quantity<Unit,Y>& val2)
1198 {
1199 return val1.value() != val2.value();
1200 }
1201
1202 /// runtime operator<
1203 template<class Unit,
1204 class X,
1205 class Y>
1206 inline
1207 bool
1208 operator<(const quantity<Unit,X>& val1,
1209 const quantity<Unit,Y>& val2)
1210 {
1211 return val1.value() < val2.value();
1212 }
1213
1214 /// runtime operator<=
1215 template<class Unit,
1216 class X,
1217 class Y>
1218 inline
1219 bool
1220 operator<=(const quantity<Unit,X>& val1,
1221 const quantity<Unit,Y>& val2)
1222 {
1223 return val1.value() <= val2.value();
1224 }
1225
1226 /// runtime operator>
1227 template<class Unit,
1228 class X,
1229 class Y>
1230 inline
1231 bool
1232 operator>(const quantity<Unit,X>& val1,
1233 const quantity<Unit,Y>& val2)
1234 {
1235 return val1.value() > val2.value();
1236 }
1237
1238 /// runtime operator>=
1239 template<class Unit,
1240 class X,
1241 class Y>
1242 inline
1243 bool
1244 operator>=(const quantity<Unit,X>& val1,
1245 const quantity<Unit,Y>& val2)
1246 {
1247 return val1.value() >= val2.value();
1248 }
1249
1250 } // namespace units
1251
1252 } // namespace boost
1253
1254 #endif // BOOST_UNITS_QUANTITY_HPP