1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and
2 // unit/quantity manipulation and conversion
4 // Copyright (C) 2003-2008 Matthias Christian Schabel
5 // Copyright (C) 2007-2008 Steven Watanabe
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
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>
43 template<class T, class Enable = void>
44 struct is_base_unit : mpl::false_ {};
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 :
55 boost::is_convertible<Source, Destination>,
58 boost::is_arithmetic<Source>,
59 boost::is_arithmetic<Destination>,
62 is_integral<Destination>,
63 mpl::not_<is_integral<Source> >
65 is_narrowing_conversion_impl<Source, Destination>
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
83 struct disable_if_is_same<T, T> {};
88 template<class Unit,class Y>
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*******);
96 typedef quantity<Unit,Y> this_type;
99 typedef Unit unit_type;
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,
121 unit_type force_unit_instantiation;
127 this_type& operator=(const this_type& source)
134 #ifndef BOOST_NO_SFINAE
136 /// implicit conversion between value types is allowed if allowed for value types themselves
138 quantity(const quantity<Unit,YY>& source,
139 typename boost::enable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
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
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);
156 /// implicit conversion between value types is allowed if allowed for value types themselves
158 quantity(const quantity<Unit,YY>& source) :
161 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
162 BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
167 /// implicit assignment between value types is allowed if allowed for value types themselves
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);
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>
183 quantity(const quantity<Unit2,YY>& source,
184 typename boost::disable_if<
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
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<
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
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));
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));
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);
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();
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();
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();
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();
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); }
287 explicit quantity(const value_type& val, int) : val_(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
297 template<class System,class Y>
298 class quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(System),Y>
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;
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);
326 this_type& operator=(const this_type& source)
333 #ifndef BOOST_NO_SFINAE
335 /// implicit conversion between value types is allowed if allowed for value types themselves
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) :
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
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);
355 /// implicit conversion between value types is allowed if allowed for value types themselves
357 quantity(const quantity<unit<dimension_type,system_type>,YY>& source) :
360 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
361 BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
366 /// implicit assignment between value types is allowed if allowed for value types themselves
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);
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,
383 typename boost::enable_if<
385 detail::is_non_narrowing_conversion<Y2, Y>,
386 detail::is_dimensionless_system<System2>
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
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,
404 typename boost::enable_if<
406 boost::mpl::not_<detail::is_non_narrowing_conversion<Y2, Y> >,
407 detail::is_dimensionless_system<System2>
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
416 val_(static_cast<Y>(source.value()))
418 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
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) :
428 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
429 BOOST_STATIC_ASSERT((boost::is_convertible<Y2, Y>::value == true));
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);
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);
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); }
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> {};
486 class quantity<int, T> {};
493 #if BOOST_UNITS_HAS_BOOST_TYPEOF
495 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
497 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::quantity, 2)
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> >
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> >
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>
534 quantity_cast(Y& source)
536 detail::quantity_cast_helper<X,Y> qch;
541 template<class X,class Y>
544 quantity_cast(const Y& source)
546 detail::quantity_cast_helper<X,const Y> qch;
552 template<class Unit,class Y>
553 inline void swap(quantity<Unit,Y>& lhs, quantity<Unit,Y>& rhs)
556 swap(quantity_cast<Y&>(lhs),quantity_cast<Y&>(rhs));
559 /// specialize unary plus typeof helper
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
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
581 template<class Unit1,
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
595 template<class Dim1, class System1,
596 class Dim2, class System2,
599 struct add_typeof_helper< quantity<unit<Dim1, System1>,X>,quantity<unit<Dim2, System2>,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
616 template<class Unit1,
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,
632 struct subtract_typeof_helper< quantity<unit<Dim1, System1>,X>,quantity<unit<Dim2, System2>,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
649 template<class System,
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
661 template<class System,
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
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;
687 struct multiply_typeof_helper< one,quantity<Unit,Y> >
689 typedef quantity<Unit,Y> type;
692 /// quantity times scalar typeof helper
697 struct multiply_typeof_helper< quantity<Unit,X>,Y >
699 typedef typename multiply_typeof_helper<X,Y>::type value_type;
700 typedef Unit unit_type;
701 typedef quantity<unit_type,value_type> type;
708 struct multiply_typeof_helper< quantity<Unit,X>,one >
710 typedef quantity<Unit,X> type;
713 /// unit times quantity typeof helper
719 struct multiply_typeof_helper< unit<Dim,System>,quantity<Unit,X> >
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;
726 /// quantity times unit typeof helper
732 struct multiply_typeof_helper< quantity<Unit,X>,unit<Dim,System> >
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;
739 /// quantity times quantity typeof helper
741 template<class Unit1,
745 struct multiply_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
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;
752 /// scalar divided by unit typeof helper
754 template<class System,
757 struct divide_typeof_helper< X,unit<Dim,System> >
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;
764 /// unit divided by scalar typeof helper
766 template<class System,
769 struct divide_typeof_helper< unit<Dim,System>,X >
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;
776 /// scalar divided by quantity typeof helper
781 struct divide_typeof_helper< X,quantity<Unit,Y> >
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;
792 struct divide_typeof_helper< one,quantity<Unit,Y> >
794 typedef quantity<Unit,Y> type;
797 /// quantity divided by scalar typeof helper
802 struct divide_typeof_helper< quantity<Unit,X>,Y >
804 typedef typename divide_typeof_helper<X,Y>::type value_type;
805 typedef Unit unit_type;
806 typedef quantity<unit_type,value_type> type;
813 struct divide_typeof_helper< quantity<Unit,X>,one >
815 typedef quantity<Unit,X> type;
818 /// unit divided by quantity typeof helper
824 struct divide_typeof_helper< unit<Dim,System>,quantity<Unit,X> >
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;
831 /// quantity divided by unit typeof helper
837 struct divide_typeof_helper< quantity<Unit,X>,unit<Dim,System> >
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;
844 /// quantity divided by quantity typeof helper
846 template<class Unit1,
850 struct divide_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
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;
857 /// specialize power typeof helper
859 template<class Unit,long N,long D,class Y>
860 struct power_typeof_helper< quantity<Unit,Y>,static_rational<N,D> >
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;
866 static type value(const quantity<Unit,Y>& x)
868 return type::from_value(power_typeof_helper<Y,static_rational<N,D> >::value(x.value()));
872 /// specialize root typeof helper
874 template<class Unit,long N,long D,class Y>
875 struct root_typeof_helper< quantity<Unit,Y>,static_rational<N,D> >
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;
881 static type value(const quantity<Unit,Y>& x)
883 return type::from_value(root_typeof_helper<Y,static_rational<N,D> >::value(x.value()));
887 /// runtime unit times scalar
889 template<class System,
893 typename multiply_typeof_helper< unit<Dim,System>,Y >::type
894 operator*(const unit<Dim,System>&,const Y& rhs)
896 typedef typename multiply_typeof_helper< unit<Dim,System>,Y >::type type;
898 return type::from_value(rhs);
901 /// runtime unit divided by scalar
902 template<class System,
906 typename divide_typeof_helper< unit<Dim,System>,Y >::type
907 operator/(const unit<Dim,System>&,const Y& rhs)
909 typedef typename divide_typeof_helper<unit<Dim,System>,Y>::type type;
911 return type::from_value(Y(1)/rhs);
914 /// runtime scalar times unit
915 template<class System,
919 typename multiply_typeof_helper< Y,unit<Dim,System> >::type
920 operator*(const Y& lhs,const unit<Dim,System>&)
922 typedef typename multiply_typeof_helper< Y,unit<Dim,System> >::type type;
924 return type::from_value(lhs);
927 /// runtime scalar divided by unit
928 template<class System,
932 typename divide_typeof_helper< Y,unit<Dim,System> >::type
933 operator/(const Y& lhs,const unit<Dim,System>&)
935 typedef typename divide_typeof_helper< Y,unit<Dim,System> >::type type;
937 return type::from_value(lhs);
940 ///// runtime quantity times scalar
941 //template<class Unit,
945 //typename multiply_typeof_helper< quantity<Unit,X>,Y >::type
946 //operator*(const quantity<Unit,X>& lhs,const Y& rhs)
948 // typedef typename multiply_typeof_helper< quantity<Unit,X>,Y >::type type;
950 // return type::from_value(lhs.value()*rhs);
953 ///// runtime scalar times quantity
954 //template<class Unit,
958 //typename multiply_typeof_helper< X,quantity<Unit,Y> >::type
959 //operator*(const X& lhs,const quantity<Unit,Y>& rhs)
961 // typedef typename multiply_typeof_helper< X,quantity<Unit,Y> >::type type;
963 // return type::from_value(lhs*rhs.value());
966 /// runtime quantity times scalar
970 typename multiply_typeof_helper< quantity<Unit,X>,X >::type
971 operator*(const quantity<Unit,X>& lhs,const X& rhs)
973 typedef typename multiply_typeof_helper< quantity<Unit,X>,X >::type type;
975 return type::from_value(lhs.value()*rhs);
978 /// runtime scalar times quantity
982 typename multiply_typeof_helper< X,quantity<Unit,X> >::type
983 operator*(const X& lhs,const quantity<Unit,X>& rhs)
985 typedef typename multiply_typeof_helper< X,quantity<Unit,X> >::type type;
987 return type::from_value(lhs*rhs.value());
990 ///// runtime quantity divided by scalar
991 //template<class Unit,
995 //typename divide_typeof_helper< quantity<Unit,X>,Y >::type
996 //operator/(const quantity<Unit,X>& lhs,const Y& rhs)
998 // typedef typename divide_typeof_helper< quantity<Unit,X>,Y >::type type;
1000 // return type::from_value(lhs.value()/rhs);
1003 ///// runtime scalar divided by quantity
1004 //template<class Unit,
1008 //typename divide_typeof_helper< X,quantity<Unit,Y> >::type
1009 //operator/(const X& lhs,const quantity<Unit,Y>& rhs)
1011 // typedef typename divide_typeof_helper< X,quantity<Unit,Y> >::type type;
1013 // return type::from_value(lhs/rhs.value());
1016 /// runtime quantity divided by scalar
1017 template<class Unit,
1020 typename divide_typeof_helper< quantity<Unit,X>,X >::type
1021 operator/(const quantity<Unit,X>& lhs,const X& rhs)
1023 typedef typename divide_typeof_helper< quantity<Unit,X>,X >::type type;
1025 return type::from_value(lhs.value()/rhs);
1028 /// runtime scalar divided by quantity
1029 template<class Unit,
1032 typename divide_typeof_helper< X,quantity<Unit,X> >::type
1033 operator/(const X& lhs,const quantity<Unit,X>& rhs)
1035 typedef typename divide_typeof_helper< X,quantity<Unit,X> >::type type;
1037 return type::from_value(lhs/rhs.value());
1040 /// runtime unit times quantity
1041 template<class System1,
1046 typename multiply_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type
1047 operator*(const unit<Dim1,System1>&,const quantity<Unit2,Y>& rhs)
1049 typedef typename multiply_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type type;
1051 return type::from_value(rhs.value());
1054 /// runtime unit divided by quantity
1055 template<class System1,
1060 typename divide_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type
1061 operator/(const unit<Dim1,System1>&,const quantity<Unit2,Y>& rhs)
1063 typedef typename divide_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type type;
1065 return type::from_value(Y(1)/rhs.value());
1068 /// runtime quantity times unit
1069 template<class Unit1,
1074 typename multiply_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type
1075 operator*(const quantity<Unit1,Y>& lhs,const unit<Dim2,System2>&)
1077 typedef typename multiply_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type type;
1079 return type::from_value(lhs.value());
1082 /// runtime quantity divided by unit
1083 template<class Unit1,
1088 typename divide_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type
1089 operator/(const quantity<Unit1,Y>& lhs,const unit<Dim2,System2>&)
1091 typedef typename divide_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type type;
1093 return type::from_value(lhs.value());
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)
1101 typedef typename unary_plus_typeof_helper< quantity<Unit,Y> >::type type;
1103 return type::from_value(+val.value());
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)
1111 typedef typename unary_minus_typeof_helper< quantity<Unit,Y> >::type type;
1113 return type::from_value(-val.value());
1116 /// runtime quantity plus quantity
1117 template<class Unit1,
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)
1126 typedef typename add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type type;
1128 return type::from_value(lhs.value()+rhs.value());
1131 /// runtime quantity minus quantity
1132 template<class Unit1,
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)
1141 typedef typename subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type type;
1143 return type::from_value(lhs.value()-rhs.value());
1146 /// runtime quantity times quantity
1147 template<class Unit1,
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)
1156 typedef typename multiply_typeof_helper< quantity<Unit1,X>,
1157 quantity<Unit2,Y> >::type type;
1159 return type::from_value(lhs.value()*rhs.value());
1162 /// runtime quantity divided by quantity
1163 template<class Unit1,
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)
1172 typedef typename divide_typeof_helper< quantity<Unit1,X>,
1173 quantity<Unit2,Y> >::type type;
1175 return type::from_value(lhs.value()/rhs.value());
1178 /// runtime operator==
1179 template<class Unit,
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,
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,
1208 operator<(const quantity<Unit,X>& val1,
1209 const quantity<Unit,Y>& val2)
1211 return val1.value() < val2.value();
1214 /// runtime operator<=
1215 template<class Unit,
1220 operator<=(const quantity<Unit,X>& val1,
1221 const quantity<Unit,Y>& val2)
1223 return val1.value() <= val2.value();
1226 /// runtime operator>
1227 template<class Unit,
1232 operator>(const quantity<Unit,X>& val1,
1233 const quantity<Unit,Y>& val2)
1235 return val1.value() > val2.value();
1238 /// runtime operator>=
1239 template<class Unit,
1244 operator>=(const quantity<Unit,X>& val1,
1245 const quantity<Unit,Y>& val2)
1247 return val1.value() >= val2.value();
1250 } // namespace units
1252 } // namespace boost
1254 #endif // BOOST_UNITS_QUANTITY_HPP