fix doc example typo
[boost.git] / boost / units / quantity.hpp
blob4fe916dcc453cbcac234e75b6ce423244f16a66d
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)
11 #ifndef BOOST_UNITS_QUANTITY_HPP
12 #define BOOST_UNITS_QUANTITY_HPP
14 #include <algorithm>
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>
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>
37 namespace boost {
39 namespace units {
41 namespace detail {
43 template<class T, class Enable = void>
44 struct is_base_unit : mpl::false_ {};
46 template<class T>
47 struct is_base_unit<T, typename T::boost_units_is_base_unit_type> : mpl::true_ {};
49 template<class Source, class Destination>
50 struct is_narrowing_conversion_impl : mpl::bool_<(sizeof(Source) > sizeof(Destination))> {};
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> >
65 is_narrowing_conversion_impl<Source, Destination>
70 {};
72 template<>
73 struct is_non_narrowing_conversion<long double, double> : mpl::false_ {};
75 // msvc 7.1 needs extra disambiguation
76 template<class T, class U>
77 struct disable_if_is_same
79 typedef void type;
82 template<class T>
83 struct disable_if_is_same<T, T> {};
87 /// class declaration
88 template<class Unit,class Y = double>
89 class quantity
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;
98 typedef Y value_type;
99 typedef Unit unit_type;
101 quantity() : val_()
103 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
106 quantity(unspecified_null_pointer_constant_type) : val_()
108 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
111 quantity(const this_type& source) : val_(source.val_)
113 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
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;
123 #endif
125 //~quantity() { }
127 this_type& operator=(const this_type& source)
129 val_ = source.val_;
131 return *this;
134 #ifndef BOOST_NO_SFINAE
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())
142 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
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()))
151 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
154 #else
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())
161 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
162 BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
165 #endif
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)
171 BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
173 *this = this_type(source);
175 return *this;
178 #ifndef BOOST_NO_SFINAE
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>
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())
195 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
196 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
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>
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())
211 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
212 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
215 #else
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())
223 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
224 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
227 #endif
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)
234 BOOST_STATIC_ASSERT((is_implicitly_convertible<Unit2,unit_type>::value == true));
235 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
237 *this = this_type(source);
239 return *this;
242 const value_type& value() const { return val_; } ///< constant accessor to value
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)
248 BOOST_STATIC_ASSERT((boost::is_same<typename add_typeof_helper<Unit, Unit2>::type, Unit>::value));
249 val_ += source.value();
250 return *this;
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)
257 BOOST_STATIC_ASSERT((boost::is_same<typename subtract_typeof_helper<Unit, Unit2>::type, Unit>::value));
258 val_ -= source.value();
259 return *this;
262 template<class Unit2, class YY>
263 this_type& operator*=(const quantity<Unit2, YY>& source)
265 BOOST_STATIC_ASSERT((boost::is_same<typename multiply_typeof_helper<Unit, Unit2>::type, Unit>::value));
266 val_ *= source.value();
267 return *this;
270 template<class Unit2, class YY>
271 this_type& operator/=(const quantity<Unit2, YY>& source)
273 BOOST_STATIC_ASSERT((boost::is_same<typename divide_typeof_helper<Unit, Unit2>::type, Unit>::value));
274 val_ /= source.value();
275 return *this;
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; }
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); }
286 protected:
287 explicit quantity(const value_type& val, int) : val_(val) { }
289 private:
290 value_type val_;
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>
300 public:
301 typedef quantity<unit<dimensionless_type,System>,Y> this_type;
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;
308 quantity() : val_()
310 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
313 /// construction from raw @c value_type is allowed
314 quantity(value_type val) : val_(val)
316 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
319 quantity(const this_type& source) : val_(source.val_)
321 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
324 //~quantity() { }
326 this_type& operator=(const this_type& source)
328 val_ = source.val_;
330 return *this;
333 #ifndef BOOST_NO_SFINAE
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())
341 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
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()))
350 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
353 #else
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())
360 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
361 BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
364 #endif
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)
370 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
372 *this = this_type(source);
374 return *this;
377 #if 1
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>
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
395 val_(source.value())
397 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
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>
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
416 val_(static_cast<Y>(source.value()))
418 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
421 #else
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())
428 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
429 BOOST_STATIC_ASSERT((boost::is_convertible<Y2, Y>::value == true));
432 #endif
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())
441 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
444 #ifndef __SUNPRO_CC
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)
450 *this = this_type(source);
452 return *this;
455 #endif
457 /// implicit conversion to @c value_type is allowed
458 operator value_type() const { return val_; }
460 const value_type& value() const { return val_; } ///< constant accessor to value
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; }
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; }
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; }
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; }
474 /// Construct quantity directly from @c value_type.
475 static this_type from_value(const value_type& val) { return this_type(val); }
477 private:
478 value_type val_;
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
489 } // namespace units
491 } // namespace boost
493 #if BOOST_UNITS_HAS_BOOST_TYPEOF
495 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
497 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::quantity, 2)
499 #endif
501 namespace boost {
503 namespace units {
505 namespace detail {
507 /// helper class for quantity_cast
508 template<class X,class Y> struct quantity_cast_helper;
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> >
514 typedef Y type;
516 type operator()(quantity<Unit,X>& source) { return const_cast<X&>(source.value()); }
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> >
523 typedef Y type;
525 type operator()(const quantity<Unit,X>& source) { return source.value(); }
528 } // namespace detail
530 /// quantity_cast provides mutating access to underlying quantity value_type
531 template<class X,class Y>
532 inline
534 quantity_cast(Y& source)
536 detail::quantity_cast_helper<X,Y> qch;
538 return qch(source);
541 template<class X,class Y>
542 inline
544 quantity_cast(const Y& source)
546 detail::quantity_cast_helper<X,const Y> qch;
548 return qch(source);
551 /// swap quantities
552 template<class Unit,class Y>
553 inline void swap(quantity<Unit,Y>& lhs, quantity<Unit,Y>& rhs)
555 using std::swap;
556 swap(quantity_cast<Y&>(lhs),quantity_cast<Y&>(rhs));
559 /// specialize unary plus typeof helper
560 /// INTERNAL ONLY
561 template<class Unit,class Y>
562 struct unary_plus_typeof_helper< quantity<Unit,Y> >
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;
569 /// specialize unary minus typeof helper
570 /// INTERNAL ONLY
571 template<class Unit,class Y>
572 struct unary_minus_typeof_helper< quantity<Unit,Y> >
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;
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> >
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;
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> >
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> >
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;
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> >
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;
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> >
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> >
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;
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> >
654 typedef X value_type;
655 typedef unit<Dim,System> unit_type;
656 typedef quantity<unit_type,value_type> type;
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 >
666 typedef X value_type;
667 typedef unit<Dim,System> unit_type;
668 typedef quantity<unit_type,value_type> type;
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> >
678 typedef typename multiply_typeof_helper<X,Y>::type value_type;
679 typedef Unit unit_type;
680 typedef quantity<unit_type,value_type> type;
683 /// quantity times scalar typeof helper
684 /// INTERNAL ONLY
685 template<class Unit,
686 class X,
687 class Y>
688 struct multiply_typeof_helper< quantity<Unit,X>,Y >
690 typedef typename multiply_typeof_helper<X,Y>::type value_type;
691 typedef Unit unit_type;
692 typedef quantity<unit_type,value_type> type;
695 /// unit times quantity typeof helper
696 /// INTERNAL ONLY
697 template<class Unit,
698 class System,
699 class Dim,
700 class X>
701 struct multiply_typeof_helper< unit<Dim,System>,quantity<Unit,X> >
703 typedef X value_type;
704 typedef typename multiply_typeof_helper< unit<Dim,System>,Unit >::type unit_type;
705 typedef quantity<unit_type,value_type> type;
708 /// quantity times unit typeof helper
709 /// INTERNAL ONLY
710 template<class Unit,
711 class System,
712 class Dim,
713 class X>
714 struct multiply_typeof_helper< quantity<Unit,X>,unit<Dim,System> >
716 typedef X value_type;
717 typedef typename multiply_typeof_helper< Unit,unit<Dim,System> >::type unit_type;
718 typedef quantity<unit_type,value_type> type;
721 /// quantity times quantity typeof helper
722 /// INTERNAL ONLY
723 template<class Unit1,
724 class Unit2,
725 class X,
726 class Y>
727 struct multiply_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
729 typedef typename multiply_typeof_helper<X,Y>::type value_type;
730 typedef typename multiply_typeof_helper<Unit1,Unit2>::type unit_type;
731 typedef quantity<unit_type,value_type> type;
734 /// scalar divided by unit typeof helper
735 /// INTERNAL ONLY
736 template<class System,
737 class Dim,
738 class X>
739 struct divide_typeof_helper< X,unit<Dim,System> >
741 typedef X value_type;
742 typedef typename power_typeof_helper< unit<Dim,System>,static_rational<-1> >::type unit_type;
743 typedef quantity<unit_type,value_type> type;
746 /// unit divided by scalar typeof helper
747 /// INTERNAL ONLY
748 template<class System,
749 class Dim,
750 class X>
751 struct divide_typeof_helper< unit<Dim,System>,X >
753 typedef typename divide_typeof_helper<X,X>::type value_type;
754 typedef unit<Dim,System> unit_type;
755 typedef quantity<unit_type,value_type> type;
758 /// scalar divided by quantity typeof helper
759 /// INTERNAL ONLY
760 template<class Unit,
761 class X,
762 class Y>
763 struct divide_typeof_helper< X,quantity<Unit,Y> >
765 typedef typename divide_typeof_helper<X,Y>::type value_type;
766 typedef typename power_typeof_helper< Unit,static_rational<-1> >::type unit_type;
767 typedef quantity<unit_type,value_type> type;
770 /// quantity divided by scalar typeof helper
771 /// INTERNAL ONLY
772 template<class Unit,
773 class X,
774 class Y>
775 struct divide_typeof_helper< quantity<Unit,X>,Y >
777 typedef typename divide_typeof_helper<X,Y>::type value_type;
778 typedef Unit unit_type;
779 typedef quantity<unit_type,value_type> type;
782 /// unit divided by quantity typeof helper
783 /// INTERNAL ONLY
784 template<class Unit,
785 class System,
786 class Dim,
787 class X>
788 struct divide_typeof_helper< unit<Dim,System>,quantity<Unit,X> >
790 typedef typename divide_typeof_helper<X,X>::type value_type;
791 typedef typename divide_typeof_helper< unit<Dim,System>,Unit >::type unit_type;
792 typedef quantity<unit_type,value_type> type;
795 /// quantity divided by unit typeof helper
796 /// INTERNAL ONLY
797 template<class Unit,
798 class System,
799 class Dim,
800 class X>
801 struct divide_typeof_helper< quantity<Unit,X>,unit<Dim,System> >
803 typedef X value_type;
804 typedef typename divide_typeof_helper< Unit,unit<Dim,System> >::type unit_type;
805 typedef quantity<unit_type,value_type> type;
808 /// quantity divided by quantity typeof helper
809 /// INTERNAL ONLY
810 template<class Unit1,
811 class Unit2,
812 class X,
813 class Y>
814 struct divide_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
816 typedef typename divide_typeof_helper<X,Y>::type value_type;
817 typedef typename divide_typeof_helper<Unit1,Unit2>::type unit_type;
818 typedef quantity<unit_type,value_type> type;
821 /// specialize power typeof helper
822 /// INTERNAL ONLY
823 template<class Unit,long N,long D,class Y>
824 struct power_typeof_helper< quantity<Unit,Y>,static_rational<N,D> >
826 typedef typename power_typeof_helper<Y,static_rational<N,D> >::type value_type;
827 typedef typename power_typeof_helper<Unit,static_rational<N,D> >::type unit_type;
828 typedef quantity<unit_type,value_type> type;
830 static type value(const quantity<Unit,Y>& x)
832 return type::from_value(power_typeof_helper<Y,static_rational<N,D> >::value(x.value()));
836 /// specialize root typeof helper
837 /// INTERNAL ONLY
838 template<class Unit,long N,long D,class Y>
839 struct root_typeof_helper< quantity<Unit,Y>,static_rational<N,D> >
841 typedef typename root_typeof_helper<Y,static_rational<N,D> >::type value_type;
842 typedef typename root_typeof_helper<Unit,static_rational<N,D> >::type unit_type;
843 typedef quantity<unit_type,value_type> type;
845 static type value(const quantity<Unit,Y>& x)
847 return type::from_value(root_typeof_helper<Y,static_rational<N,D> >::value(x.value()));
851 /// runtime unit times scalar
852 /// INTERNAL ONLY
853 template<class System,
854 class Dim,
855 class Y>
856 inline
857 typename multiply_typeof_helper< unit<Dim,System>,Y >::type
858 operator*(const unit<Dim,System>&,const Y& rhs)
860 typedef typename multiply_typeof_helper< unit<Dim,System>,Y >::type type;
862 return type::from_value(rhs);
865 /// runtime unit divided by scalar
866 template<class System,
867 class Dim,
868 class Y>
869 inline
870 typename divide_typeof_helper< unit<Dim,System>,Y >::type
871 operator/(const unit<Dim,System>&,const Y& rhs)
873 typedef typename divide_typeof_helper<unit<Dim,System>,Y>::type type;
875 return type::from_value(Y(1)/rhs);
878 /// runtime scalar times unit
879 template<class System,
880 class Dim,
881 class Y>
882 inline
883 typename multiply_typeof_helper< Y,unit<Dim,System> >::type
884 operator*(const Y& lhs,const unit<Dim,System>&)
886 typedef typename multiply_typeof_helper< Y,unit<Dim,System> >::type type;
888 return type::from_value(lhs);
891 /// runtime scalar divided by unit
892 template<class System,
893 class Dim,
894 class Y>
895 inline
896 typename divide_typeof_helper< Y,unit<Dim,System> >::type
897 operator/(const Y& lhs,const unit<Dim,System>&)
899 typedef typename divide_typeof_helper< Y,unit<Dim,System> >::type type;
901 return type::from_value(lhs);
904 ///// runtime quantity times scalar
905 //template<class Unit,
906 // class X,
907 // class Y>
908 //inline
909 //typename multiply_typeof_helper< quantity<Unit,X>,Y >::type
910 //operator*(const quantity<Unit,X>& lhs,const Y& rhs)
912 // typedef typename multiply_typeof_helper< quantity<Unit,X>,Y >::type type;
914 // return type::from_value(lhs.value()*rhs);
917 ///// runtime scalar times quantity
918 //template<class Unit,
919 // class X,
920 // class Y>
921 //inline
922 //typename multiply_typeof_helper< X,quantity<Unit,Y> >::type
923 //operator*(const X& lhs,const quantity<Unit,Y>& rhs)
925 // typedef typename multiply_typeof_helper< X,quantity<Unit,Y> >::type type;
927 // return type::from_value(lhs*rhs.value());
930 /// runtime quantity times scalar
931 template<class Unit,
932 class X>
933 inline
934 typename multiply_typeof_helper< quantity<Unit,X>,X >::type
935 operator*(const quantity<Unit,X>& lhs,const X& rhs)
937 typedef typename multiply_typeof_helper< quantity<Unit,X>,X >::type type;
939 return type::from_value(lhs.value()*rhs);
942 /// runtime scalar times quantity
943 template<class Unit,
944 class X>
945 inline
946 typename multiply_typeof_helper< X,quantity<Unit,X> >::type
947 operator*(const X& lhs,const quantity<Unit,X>& rhs)
949 typedef typename multiply_typeof_helper< X,quantity<Unit,X> >::type type;
951 return type::from_value(lhs*rhs.value());
954 ///// runtime quantity divided by scalar
955 //template<class Unit,
956 // class X,
957 // class Y>
958 //inline
959 //typename divide_typeof_helper< quantity<Unit,X>,Y >::type
960 //operator/(const quantity<Unit,X>& lhs,const Y& rhs)
962 // typedef typename divide_typeof_helper< quantity<Unit,X>,Y >::type type;
964 // return type::from_value(lhs.value()/rhs);
967 ///// runtime scalar divided by quantity
968 //template<class Unit,
969 // class X,
970 // class Y>
971 //inline
972 //typename divide_typeof_helper< X,quantity<Unit,Y> >::type
973 //operator/(const X& lhs,const quantity<Unit,Y>& rhs)
975 // typedef typename divide_typeof_helper< X,quantity<Unit,Y> >::type type;
977 // return type::from_value(lhs/rhs.value());
980 /// runtime quantity divided by scalar
981 template<class Unit,
982 class X>
983 inline
984 typename divide_typeof_helper< quantity<Unit,X>,X >::type
985 operator/(const quantity<Unit,X>& lhs,const X& rhs)
987 typedef typename divide_typeof_helper< quantity<Unit,X>,X >::type type;
989 return type::from_value(lhs.value()/rhs);
992 /// runtime scalar divided by quantity
993 template<class Unit,
994 class X>
995 inline
996 typename divide_typeof_helper< X,quantity<Unit,X> >::type
997 operator/(const X& lhs,const quantity<Unit,X>& rhs)
999 typedef typename divide_typeof_helper< X,quantity<Unit,X> >::type type;
1001 return type::from_value(lhs/rhs.value());
1004 /// runtime unit times quantity
1005 template<class System1,
1006 class Dim1,
1007 class Unit2,
1008 class Y>
1009 inline
1010 typename multiply_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type
1011 operator*(const unit<Dim1,System1>&,const quantity<Unit2,Y>& rhs)
1013 typedef typename multiply_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type type;
1015 return type::from_value(rhs.value());
1018 /// runtime unit divided by quantity
1019 template<class System1,
1020 class Dim1,
1021 class Unit2,
1022 class Y>
1023 inline
1024 typename divide_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type
1025 operator/(const unit<Dim1,System1>&,const quantity<Unit2,Y>& rhs)
1027 typedef typename divide_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type type;
1029 return type::from_value(Y(1)/rhs.value());
1032 /// runtime quantity times unit
1033 template<class Unit1,
1034 class System2,
1035 class Dim2,
1036 class Y>
1037 inline
1038 typename multiply_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type
1039 operator*(const quantity<Unit1,Y>& lhs,const unit<Dim2,System2>&)
1041 typedef typename multiply_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type type;
1043 return type::from_value(lhs.value());
1046 /// runtime quantity divided by unit
1047 template<class Unit1,
1048 class System2,
1049 class Dim2,
1050 class Y>
1051 inline
1052 typename divide_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type
1053 operator/(const quantity<Unit1,Y>& lhs,const unit<Dim2,System2>&)
1055 typedef typename divide_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type type;
1057 return type::from_value(lhs.value());
1060 /// runtime unary plus quantity
1061 template<class Unit,class Y>
1062 typename unary_plus_typeof_helper< quantity<Unit,Y> >::type
1063 operator+(const quantity<Unit,Y>& val)
1065 typedef typename unary_plus_typeof_helper< quantity<Unit,Y> >::type type;
1067 return type::from_value(+val.value());
1070 /// runtime unary minus quantity
1071 template<class Unit,class Y>
1072 typename unary_minus_typeof_helper< quantity<Unit,Y> >::type
1073 operator-(const quantity<Unit,Y>& val)
1075 typedef typename unary_minus_typeof_helper< quantity<Unit,Y> >::type type;
1077 return type::from_value(-val.value());
1080 /// runtime quantity plus quantity
1081 template<class Unit1,
1082 class Unit2,
1083 class X,
1084 class Y>
1085 inline
1086 typename add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1087 operator+(const quantity<Unit1,X>& lhs,
1088 const quantity<Unit2,Y>& rhs)
1090 typedef typename add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type type;
1092 return type::from_value(lhs.value()+rhs.value());
1095 /// runtime quantity minus quantity
1096 template<class Unit1,
1097 class Unit2,
1098 class X,
1099 class Y>
1100 inline
1101 typename subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1102 operator-(const quantity<Unit1,X>& lhs,
1103 const quantity<Unit2,Y>& rhs)
1105 typedef typename subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type type;
1107 return type::from_value(lhs.value()-rhs.value());
1110 /// runtime quantity times quantity
1111 template<class Unit1,
1112 class Unit2,
1113 class X,
1114 class Y>
1115 inline
1116 typename multiply_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1117 operator*(const quantity<Unit1,X>& lhs,
1118 const quantity<Unit2,Y>& rhs)
1120 typedef typename multiply_typeof_helper< quantity<Unit1,X>,
1121 quantity<Unit2,Y> >::type type;
1123 return type::from_value(lhs.value()*rhs.value());
1126 /// runtime quantity divided by quantity
1127 template<class Unit1,
1128 class Unit2,
1129 class X,
1130 class Y>
1131 inline
1132 typename divide_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1133 operator/(const quantity<Unit1,X>& lhs,
1134 const quantity<Unit2,Y>& rhs)
1136 typedef typename divide_typeof_helper< quantity<Unit1,X>,
1137 quantity<Unit2,Y> >::type type;
1139 return type::from_value(lhs.value()/rhs.value());
1142 /// runtime operator==
1143 template<class Unit,
1144 class X,
1145 class Y>
1146 inline
1147 bool
1148 operator==(const quantity<Unit,X>& val1,
1149 const quantity<Unit,Y>& val2)
1151 return val1.value() == val2.value();
1154 /// runtime operator!=
1155 template<class Unit,
1156 class X,
1157 class Y>
1158 inline
1159 bool
1160 operator!=(const quantity<Unit,X>& val1,
1161 const quantity<Unit,Y>& val2)
1163 return val1.value() != val2.value();
1166 /// runtime operator<
1167 template<class Unit,
1168 class X,
1169 class Y>
1170 inline
1171 bool
1172 operator<(const quantity<Unit,X>& val1,
1173 const quantity<Unit,Y>& val2)
1175 return val1.value() < val2.value();
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)
1187 return val1.value() <= val2.value();
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)
1199 return val1.value() > val2.value();
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)
1211 return val1.value() >= val2.value();
1214 } // namespace units
1216 } // namespace boost
1218 #endif // BOOST_UNITS_QUANTITY_HPP