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
= double>
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
;
683 /// quantity times scalar typeof helper
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
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
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
723 template<class Unit1
,
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
736 template<class System
,
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
748 template<class System
,
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
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
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
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
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
810 template<class Unit1
,
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
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
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
853 template<class System
,
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
,
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
,
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
,
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,
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,
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
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
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,
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,
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
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
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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 } // namespace units
1216 } // namespace boost
1218 #endif // BOOST_UNITS_QUANTITY_HPP