Chris@16: // Boost.Units - A C++ library for zero-overhead dimensional analysis and Chris@16: // unit/quantity manipulation and conversion Chris@16: // Chris@16: // Copyright (C) 2003-2008 Matthias Christian Schabel Chris@16: // Copyright (C) 2007-2008 Steven Watanabe Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_UNITS_QUANTITY_HPP Chris@16: #define BOOST_UNITS_QUANTITY_HPP Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: namespace units { Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: template Chris@16: struct is_base_unit : mpl::false_ {}; Chris@16: Chris@16: template Chris@16: struct is_base_unit : mpl::true_ {}; Chris@16: Chris@16: template Chris@16: struct is_narrowing_conversion_impl : mpl::bool_<(sizeof(Source) > sizeof(Destination))> {}; Chris@16: Chris@16: template Chris@16: struct is_non_narrowing_conversion : Chris@16: mpl::and_< Chris@16: boost::is_convertible, Chris@16: mpl::not_< Chris@16: mpl::and_< Chris@16: boost::is_arithmetic, Chris@16: boost::is_arithmetic, Chris@16: mpl::or_< Chris@16: mpl::and_< Chris@16: is_integral, Chris@16: mpl::not_ > Chris@16: >, Chris@16: is_narrowing_conversion_impl Chris@16: > Chris@16: > Chris@16: > Chris@16: > Chris@16: {}; Chris@16: Chris@16: template<> Chris@16: struct is_non_narrowing_conversion : mpl::false_ {}; Chris@16: Chris@16: // msvc 7.1 needs extra disambiguation Chris@16: template Chris@16: struct disable_if_is_same Chris@16: { Chris@16: typedef void type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct disable_if_is_same {}; Chris@16: Chris@16: } Chris@16: Chris@16: /// class declaration Chris@101: template Chris@16: class quantity Chris@16: { Chris@16: // base units are not the same as units. Chris@16: BOOST_MPL_ASSERT_NOT((detail::is_base_unit)); Chris@16: enum { force_instantiation_of_unit = sizeof(Unit) }; Chris@16: typedef void (quantity::*unspecified_null_pointer_constant_type)(int*******); Chris@16: public: Chris@16: typedef quantity this_type; Chris@16: Chris@16: typedef Y value_type; Chris@16: typedef Unit unit_type; Chris@16: Chris@16: quantity() : val_() Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: quantity(unspecified_null_pointer_constant_type) : val_() Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: quantity(const this_type& source) : val_(source.val_) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: // Need to make sure that the destructor of Chris@16: // Unit which contains the checking is instantiated, Chris@16: // on sun. Chris@16: #ifdef __SUNPRO_CC Chris@16: ~quantity() { Chris@16: unit_type force_unit_instantiation; Chris@16: } Chris@16: #endif Chris@16: Chris@16: //~quantity() { } Chris@16: Chris@16: this_type& operator=(const this_type& source) Chris@16: { Chris@16: val_ = source.val_; Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_SFINAE Chris@16: Chris@16: /// implicit conversion between value types is allowed if allowed for value types themselves Chris@16: template Chris@16: quantity(const quantity& source, Chris@16: typename boost::enable_if >::type* = 0) : Chris@16: val_(source.value()) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: /// implicit conversion between value types is not allowed if not allowed for value types themselves Chris@16: template Chris@16: explicit quantity(const quantity& source, Chris@16: typename boost::disable_if >::type* = 0) : Chris@16: val_(static_cast(source.value())) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: /// implicit conversion between value types is allowed if allowed for value types themselves Chris@16: template Chris@16: quantity(const quantity& source) : Chris@16: val_(source.value()) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: BOOST_STATIC_ASSERT((boost::is_convertible::value == true)); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: /// implicit assignment between value types is allowed if allowed for value types themselves Chris@16: template Chris@16: this_type& operator=(const quantity& source) Chris@16: { Chris@16: BOOST_STATIC_ASSERT((boost::is_convertible::value == true)); Chris@16: Chris@16: *this = this_type(source); Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_SFINAE Chris@16: Chris@16: /// explicit conversion between different unit systems is allowed if implicit conversion is disallowed Chris@16: template Chris@16: explicit Chris@16: quantity(const quantity& source, Chris@16: typename boost::disable_if< Chris@16: mpl::and_< Chris@16: //is_implicitly_convertible should be undefined when the Chris@16: //units are not convertible at all Chris@16: typename is_implicitly_convertible::type, Chris@16: detail::is_non_narrowing_conversion Chris@16: >, Chris@16: typename detail::disable_if_is_same::type Chris@16: >::type* = 0) Chris@16: : val_(conversion_helper,this_type>::convert(source).value()) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: BOOST_STATIC_ASSERT((boost::is_convertible::value == true)); Chris@16: } Chris@16: Chris@16: /// implicit conversion between different unit systems is allowed if each fundamental dimension is implicitly convertible Chris@16: template Chris@16: quantity(const quantity& source, Chris@16: typename boost::enable_if< Chris@16: mpl::and_< Chris@16: typename is_implicitly_convertible::type, Chris@16: detail::is_non_narrowing_conversion Chris@16: >, Chris@16: typename detail::disable_if_is_same::type Chris@16: >::type* = 0) Chris@16: : val_(conversion_helper,this_type>::convert(source).value()) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: BOOST_STATIC_ASSERT((boost::is_convertible::value == true)); Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: /// without SFINAE we can't distinguish between explicit and implicit conversions so Chris@16: /// the conversion is always explicit Chris@16: template Chris@16: explicit quantity(const quantity& source) Chris@16: : val_(conversion_helper,this_type>::convert(source).value()) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: BOOST_STATIC_ASSERT((boost::is_convertible::value == true)); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: /// implicit assignment between different unit systems is allowed if each fundamental dimension is implicitly convertible Chris@16: template Chris@16: this_type& operator=(const quantity& source) Chris@16: { Chris@16: Chris@16: BOOST_STATIC_ASSERT((is_implicitly_convertible::value == true)); Chris@16: BOOST_STATIC_ASSERT((boost::is_convertible::value == true)); Chris@16: Chris@16: *this = this_type(source); Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: const value_type& value() const { return val_; } ///< constant accessor to value Chris@16: Chris@16: ///< can add a quantity of the same type if add_typeof_helper::type is convertible to value_type Chris@16: template Chris@16: this_type& operator+=(const quantity& source) Chris@16: { Chris@16: BOOST_STATIC_ASSERT((boost::is_same::type, Unit>::value)); Chris@16: val_ += source.value(); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: ///< can subtract a quantity of the same type if subtract_typeof_helper::type is convertible to value_type Chris@16: template Chris@16: this_type& operator-=(const quantity& source) Chris@16: { Chris@16: BOOST_STATIC_ASSERT((boost::is_same::type, Unit>::value)); Chris@16: val_ -= source.value(); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: template Chris@16: this_type& operator*=(const quantity& source) Chris@16: { Chris@16: BOOST_STATIC_ASSERT((boost::is_same::type, Unit>::value)); Chris@16: val_ *= source.value(); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: template Chris@16: this_type& operator/=(const quantity& source) Chris@16: { Chris@16: BOOST_STATIC_ASSERT((boost::is_same::type, Unit>::value)); Chris@16: val_ /= source.value(); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: ///< can multiply a quantity by a scalar value_type if multiply_typeof_helper::type is convertible to value_type Chris@16: this_type& operator*=(const value_type& source) { val_ *= source; return *this; } Chris@16: ///< can divide a quantity by a scalar value_type if divide_typeof_helper::type is convertible to value_type Chris@16: this_type& operator/=(const value_type& source) { val_ /= source; return *this; } Chris@16: Chris@16: /// Construct quantity directly from @c value_type (potentially dangerous). Chris@16: static this_type from_value(const value_type& val) { return this_type(val, 0); } Chris@16: Chris@16: protected: Chris@16: explicit quantity(const value_type& val, int) : val_(val) { } Chris@16: Chris@16: private: Chris@16: value_type val_; Chris@16: }; Chris@16: Chris@16: /// Specialization for dimensionless quantities. Implicit conversions between Chris@16: /// unit systems are allowed because all dimensionless quantities are equivalent. Chris@16: /// Implicit construction and assignment from and conversion to @c value_type is Chris@16: /// also allowed. Chris@16: template Chris@16: class quantity Chris@16: { Chris@16: public: Chris@16: typedef quantity,Y> this_type; Chris@16: Chris@16: typedef Y value_type; Chris@16: typedef System system_type; Chris@16: typedef dimensionless_type dimension_type; Chris@16: typedef unit unit_type; Chris@16: Chris@16: quantity() : val_() Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: /// construction from raw @c value_type is allowed Chris@16: quantity(value_type val) : val_(val) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: quantity(const this_type& source) : val_(source.val_) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: //~quantity() { } Chris@16: Chris@16: this_type& operator=(const this_type& source) Chris@16: { Chris@16: val_ = source.val_; Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_SFINAE Chris@16: Chris@16: /// implicit conversion between value types is allowed if allowed for value types themselves Chris@16: template Chris@16: quantity(const quantity,YY>& source, Chris@16: typename boost::enable_if >::type* = 0) : Chris@16: val_(source.value()) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: /// implicit conversion between value types is not allowed if not allowed for value types themselves Chris@16: template Chris@16: explicit quantity(const quantity,YY>& source, Chris@16: typename boost::disable_if >::type* = 0) : Chris@16: val_(static_cast(source.value())) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: /// implicit conversion between value types is allowed if allowed for value types themselves Chris@16: template Chris@16: quantity(const quantity,YY>& source) : Chris@16: val_(source.value()) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: BOOST_STATIC_ASSERT((boost::is_convertible::value == true)); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: /// implicit assignment between value types is allowed if allowed for value types themselves Chris@16: template Chris@16: this_type& operator=(const quantity,YY>& source) Chris@16: { Chris@16: BOOST_STATIC_ASSERT((boost::is_convertible::value == true)); Chris@16: Chris@16: *this = this_type(source); Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #if 1 Chris@16: Chris@16: /// implicit conversion between different unit systems is allowed Chris@16: template Chris@16: quantity(const quantity,Y2>& source, Chris@16: #ifdef __SUNPRO_CC Chris@16: typename boost::enable_if< Chris@16: boost::mpl::and_< Chris@16: detail::is_non_narrowing_conversion, Chris@16: detail::is_dimensionless_system Chris@16: > Chris@16: >::type* = 0 Chris@16: #else Chris@16: typename boost::enable_if >::type* = 0, Chris@16: typename detail::disable_if_is_same::type* = 0, Chris@16: typename boost::enable_if >::type* = 0 Chris@16: #endif Chris@16: ) : Chris@16: val_(source.value()) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: /// implicit conversion between different unit systems is allowed Chris@16: template Chris@16: explicit quantity(const quantity,Y2>& source, Chris@16: #ifdef __SUNPRO_CC Chris@16: typename boost::enable_if< Chris@16: boost::mpl::and_< Chris@16: boost::mpl::not_ >, Chris@16: detail::is_dimensionless_system Chris@16: > Chris@16: >::type* = 0 Chris@16: #else Chris@16: typename boost::disable_if >::type* = 0, Chris@16: typename detail::disable_if_is_same::type* = 0, Chris@16: typename boost::enable_if >::type* = 0 Chris@16: #endif Chris@16: ) : Chris@16: val_(static_cast(source.value())) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: /// implicit conversion between different unit systems is allowed Chris@16: template Chris@16: quantity(const quantity >,Y2>& source) : Chris@16: val_(source.value()) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: BOOST_STATIC_ASSERT((boost::is_convertible::value == true)); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: /// conversion between different unit systems is explicit when Chris@16: /// the units are not equivalent. Chris@16: template Chris@16: explicit quantity(const quantity,Y2>& source, Chris@16: typename boost::disable_if >::type* = 0) : Chris@16: val_(conversion_helper,Y2>, this_type>::convert(source).value()) Chris@16: { Chris@16: BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y); Chris@16: } Chris@16: Chris@16: #ifndef __SUNPRO_CC Chris@16: Chris@16: /// implicit assignment between different unit systems is allowed Chris@16: template Chris@16: this_type& operator=(const quantity& source) Chris@16: { Chris@16: *this = this_type(source); Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: /// implicit conversion to @c value_type is allowed Chris@16: operator value_type() const { return val_; } Chris@16: Chris@16: const value_type& value() const { return val_; } ///< constant accessor to value Chris@16: Chris@16: ///< can add a quantity of the same type if add_typeof_helper::type is convertible to value_type Chris@16: this_type& operator+=(const this_type& source) { val_ += source.val_; return *this; } Chris@16: Chris@16: ///< can subtract a quantity of the same type if subtract_typeof_helper::type is convertible to value_type Chris@16: this_type& operator-=(const this_type& source) { val_ -= source.val_; return *this; } Chris@16: Chris@16: ///< can multiply a quantity by a scalar value_type if multiply_typeof_helper::type is convertible to value_type Chris@16: this_type& operator*=(const value_type& val) { val_ *= val; return *this; } Chris@16: Chris@16: ///< can divide a quantity by a scalar value_type if divide_typeof_helper::type is convertible to value_type Chris@16: this_type& operator/=(const value_type& val) { val_ /= val; return *this; } Chris@16: Chris@16: /// Construct quantity directly from @c value_type. Chris@16: static this_type from_value(const value_type& val) { return this_type(val); } Chris@16: Chris@16: private: Chris@16: value_type val_; Chris@16: }; Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: // HACK: For some obscure reason msvc 8.0 needs these specializations Chris@16: template Chris@16: class quantity, T> {}; Chris@16: template Chris@16: class quantity {}; Chris@16: #endif Chris@16: Chris@16: } // namespace units Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #if BOOST_UNITS_HAS_BOOST_TYPEOF Chris@16: Chris@16: #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() Chris@16: Chris@16: BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::quantity, 2) Chris@16: Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: namespace units { Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: /// helper class for quantity_cast Chris@16: template struct quantity_cast_helper; Chris@16: Chris@16: /// specialization for casting to the value type Chris@16: template Chris@16: struct quantity_cast_helper > Chris@16: { Chris@16: typedef Y type; Chris@16: Chris@16: type operator()(quantity& source) { return const_cast(source.value()); } Chris@16: }; Chris@16: Chris@16: /// specialization for casting to the value type Chris@16: template Chris@16: struct quantity_cast_helper > Chris@16: { Chris@16: typedef Y type; Chris@16: Chris@16: type operator()(const quantity& source) { return source.value(); } Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: /// quantity_cast provides mutating access to underlying quantity value_type Chris@16: template Chris@16: inline Chris@16: X Chris@16: quantity_cast(Y& source) Chris@16: { Chris@16: detail::quantity_cast_helper qch; Chris@16: Chris@16: return qch(source); Chris@16: } Chris@16: Chris@16: template Chris@16: inline Chris@16: X Chris@16: quantity_cast(const Y& source) Chris@16: { Chris@16: detail::quantity_cast_helper qch; Chris@16: Chris@16: return qch(source); Chris@16: } Chris@16: Chris@16: /// swap quantities Chris@16: template Chris@16: inline void swap(quantity& lhs, quantity& rhs) Chris@16: { Chris@16: using std::swap; Chris@16: swap(quantity_cast(lhs),quantity_cast(rhs)); Chris@16: } Chris@16: Chris@16: /// specialize unary plus typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct unary_plus_typeof_helper< quantity > Chris@16: { Chris@16: typedef typename unary_plus_typeof_helper::type value_type; Chris@16: typedef typename unary_plus_typeof_helper::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// specialize unary minus typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct unary_minus_typeof_helper< quantity > Chris@16: { Chris@16: typedef typename unary_minus_typeof_helper::type value_type; Chris@16: typedef typename unary_minus_typeof_helper::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// specialize add typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct add_typeof_helper< quantity,quantity > Chris@16: { Chris@16: typedef typename add_typeof_helper::type value_type; Chris@16: typedef typename add_typeof_helper::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// for sun CC we need to invoke SFINAE at Chris@16: /// the top level, otherwise it will silently Chris@16: /// return int. Chris@16: template Chris@16: struct add_typeof_helper< quantity,X>,quantity,Y> > Chris@16: { Chris@16: }; Chris@16: Chris@16: template Chris@16: struct add_typeof_helper< quantity,X>,quantity,Y> > Chris@16: { Chris@16: typedef typename add_typeof_helper::type value_type; Chris@16: typedef unit unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// specialize subtract typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct subtract_typeof_helper< quantity,quantity > Chris@16: { Chris@16: typedef typename subtract_typeof_helper::type value_type; Chris@16: typedef typename subtract_typeof_helper::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: // Force adding different units to fail on sun. Chris@16: template Chris@16: struct subtract_typeof_helper< quantity,X>,quantity,Y> > Chris@16: { Chris@16: }; Chris@16: Chris@16: template Chris@16: struct subtract_typeof_helper< quantity,X>,quantity,Y> > Chris@16: { Chris@16: typedef typename subtract_typeof_helper::type value_type; Chris@16: typedef unit unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// scalar times unit typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct multiply_typeof_helper< X,unit > Chris@16: { Chris@16: typedef X value_type; Chris@16: typedef unit unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// unit times scalar typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct multiply_typeof_helper< unit,X > Chris@16: { Chris@16: typedef X value_type; Chris@16: typedef unit unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// scalar times quantity typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct multiply_typeof_helper< X,quantity > Chris@16: { Chris@16: typedef typename multiply_typeof_helper::type value_type; Chris@16: typedef Unit unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// disambiguate Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct multiply_typeof_helper< one,quantity > Chris@16: { Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// quantity times scalar typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct multiply_typeof_helper< quantity,Y > Chris@16: { Chris@16: typedef typename multiply_typeof_helper::type value_type; Chris@16: typedef Unit unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// disambiguate Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct multiply_typeof_helper< quantity,one > Chris@16: { Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// unit times quantity typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct multiply_typeof_helper< unit,quantity > Chris@16: { Chris@16: typedef X value_type; Chris@16: typedef typename multiply_typeof_helper< unit,Unit >::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// quantity times unit typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct multiply_typeof_helper< quantity,unit > Chris@16: { Chris@16: typedef X value_type; Chris@16: typedef typename multiply_typeof_helper< Unit,unit >::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// quantity times quantity typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct multiply_typeof_helper< quantity,quantity > Chris@16: { Chris@16: typedef typename multiply_typeof_helper::type value_type; Chris@16: typedef typename multiply_typeof_helper::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// scalar divided by unit typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct divide_typeof_helper< X,unit > Chris@16: { Chris@16: typedef X value_type; Chris@16: typedef typename power_typeof_helper< unit,static_rational<-1> >::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// unit divided by scalar typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct divide_typeof_helper< unit,X > Chris@16: { Chris@16: typedef typename divide_typeof_helper::type value_type; Chris@16: typedef unit unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// scalar divided by quantity typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct divide_typeof_helper< X,quantity > Chris@16: { Chris@16: typedef typename divide_typeof_helper::type value_type; Chris@16: typedef typename power_typeof_helper< Unit,static_rational<-1> >::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// disambiguate Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct divide_typeof_helper< one,quantity > Chris@16: { Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// quantity divided by scalar typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct divide_typeof_helper< quantity,Y > Chris@16: { Chris@16: typedef typename divide_typeof_helper::type value_type; Chris@16: typedef Unit unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// disambiguate Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct divide_typeof_helper< quantity,one > Chris@16: { Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// unit divided by quantity typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct divide_typeof_helper< unit,quantity > Chris@16: { Chris@16: typedef typename divide_typeof_helper::type value_type; Chris@16: typedef typename divide_typeof_helper< unit,Unit >::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// quantity divided by unit typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct divide_typeof_helper< quantity,unit > Chris@16: { Chris@16: typedef X value_type; Chris@16: typedef typename divide_typeof_helper< Unit,unit >::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// quantity divided by quantity typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct divide_typeof_helper< quantity,quantity > Chris@16: { Chris@16: typedef typename divide_typeof_helper::type value_type; Chris@16: typedef typename divide_typeof_helper::type unit_type; Chris@16: typedef quantity type; Chris@16: }; Chris@16: Chris@16: /// specialize power typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct power_typeof_helper< quantity,static_rational > Chris@16: { Chris@16: typedef typename power_typeof_helper >::type value_type; Chris@16: typedef typename power_typeof_helper >::type unit_type; Chris@16: typedef quantity type; Chris@16: Chris@16: static type value(const quantity& x) Chris@16: { Chris@16: return type::from_value(power_typeof_helper >::value(x.value())); Chris@16: } Chris@16: }; Chris@16: Chris@16: /// specialize root typeof helper Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: struct root_typeof_helper< quantity,static_rational > Chris@16: { Chris@16: typedef typename root_typeof_helper >::type value_type; Chris@16: typedef typename root_typeof_helper >::type unit_type; Chris@16: typedef quantity type; Chris@16: Chris@16: static type value(const quantity& x) Chris@16: { Chris@16: return type::from_value(root_typeof_helper >::value(x.value())); Chris@16: } Chris@16: }; Chris@16: Chris@16: /// runtime unit times scalar Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: inline Chris@16: typename multiply_typeof_helper< unit,Y >::type Chris@16: operator*(const unit&,const Y& rhs) Chris@16: { Chris@16: typedef typename multiply_typeof_helper< unit,Y >::type type; Chris@16: Chris@16: return type::from_value(rhs); Chris@16: } Chris@16: Chris@16: /// runtime unit divided by scalar Chris@16: template Chris@16: inline Chris@16: typename divide_typeof_helper< unit,Y >::type Chris@16: operator/(const unit&,const Y& rhs) Chris@16: { Chris@16: typedef typename divide_typeof_helper,Y>::type type; Chris@16: Chris@16: return type::from_value(Y(1)/rhs); Chris@16: } Chris@16: Chris@16: /// runtime scalar times unit Chris@16: template Chris@16: inline Chris@16: typename multiply_typeof_helper< Y,unit >::type Chris@16: operator*(const Y& lhs,const unit&) Chris@16: { Chris@16: typedef typename multiply_typeof_helper< Y,unit >::type type; Chris@16: Chris@16: return type::from_value(lhs); Chris@16: } Chris@16: Chris@16: /// runtime scalar divided by unit Chris@16: template Chris@16: inline Chris@16: typename divide_typeof_helper< Y,unit >::type Chris@16: operator/(const Y& lhs,const unit&) Chris@16: { Chris@16: typedef typename divide_typeof_helper< Y,unit >::type type; Chris@16: Chris@16: return type::from_value(lhs); Chris@16: } Chris@16: Chris@16: ///// runtime quantity times scalar Chris@16: //template Chris@16: //inline Chris@16: //typename multiply_typeof_helper< quantity,Y >::type Chris@16: //operator*(const quantity& lhs,const Y& rhs) Chris@16: //{ Chris@16: // typedef typename multiply_typeof_helper< quantity,Y >::type type; Chris@16: // Chris@16: // return type::from_value(lhs.value()*rhs); Chris@16: //} Chris@16: // Chris@16: ///// runtime scalar times quantity Chris@16: //template Chris@16: //inline Chris@16: //typename multiply_typeof_helper< X,quantity >::type Chris@16: //operator*(const X& lhs,const quantity& rhs) Chris@16: //{ Chris@16: // typedef typename multiply_typeof_helper< X,quantity >::type type; Chris@16: // Chris@16: // return type::from_value(lhs*rhs.value()); Chris@16: //} Chris@16: Chris@16: /// runtime quantity times scalar Chris@16: template Chris@16: inline Chris@16: typename multiply_typeof_helper< quantity,X >::type Chris@16: operator*(const quantity& lhs,const X& rhs) Chris@16: { Chris@16: typedef typename multiply_typeof_helper< quantity,X >::type type; Chris@16: Chris@16: return type::from_value(lhs.value()*rhs); Chris@16: } Chris@16: Chris@16: /// runtime scalar times quantity Chris@16: template Chris@16: inline Chris@16: typename multiply_typeof_helper< X,quantity >::type Chris@16: operator*(const X& lhs,const quantity& rhs) Chris@16: { Chris@16: typedef typename multiply_typeof_helper< X,quantity >::type type; Chris@16: Chris@16: return type::from_value(lhs*rhs.value()); Chris@16: } Chris@16: Chris@16: ///// runtime quantity divided by scalar Chris@16: //template Chris@16: //inline Chris@16: //typename divide_typeof_helper< quantity,Y >::type Chris@16: //operator/(const quantity& lhs,const Y& rhs) Chris@16: //{ Chris@16: // typedef typename divide_typeof_helper< quantity,Y >::type type; Chris@16: // Chris@16: // return type::from_value(lhs.value()/rhs); Chris@16: //} Chris@16: // Chris@16: ///// runtime scalar divided by quantity Chris@16: //template Chris@16: //inline Chris@16: //typename divide_typeof_helper< X,quantity >::type Chris@16: //operator/(const X& lhs,const quantity& rhs) Chris@16: //{ Chris@16: // typedef typename divide_typeof_helper< X,quantity >::type type; Chris@16: // Chris@16: // return type::from_value(lhs/rhs.value()); Chris@16: //} Chris@16: Chris@16: /// runtime quantity divided by scalar Chris@16: template Chris@16: inline Chris@16: typename divide_typeof_helper< quantity,X >::type Chris@16: operator/(const quantity& lhs,const X& rhs) Chris@16: { Chris@16: typedef typename divide_typeof_helper< quantity,X >::type type; Chris@16: Chris@16: return type::from_value(lhs.value()/rhs); Chris@16: } Chris@16: Chris@16: /// runtime scalar divided by quantity Chris@16: template Chris@16: inline Chris@16: typename divide_typeof_helper< X,quantity >::type Chris@16: operator/(const X& lhs,const quantity& rhs) Chris@16: { Chris@16: typedef typename divide_typeof_helper< X,quantity >::type type; Chris@16: Chris@16: return type::from_value(lhs/rhs.value()); Chris@16: } Chris@16: Chris@16: /// runtime unit times quantity Chris@16: template Chris@16: inline Chris@16: typename multiply_typeof_helper< unit,quantity >::type Chris@16: operator*(const unit&,const quantity& rhs) Chris@16: { Chris@16: typedef typename multiply_typeof_helper< unit,quantity >::type type; Chris@16: Chris@16: return type::from_value(rhs.value()); Chris@16: } Chris@16: Chris@16: /// runtime unit divided by quantity Chris@16: template Chris@16: inline Chris@16: typename divide_typeof_helper< unit,quantity >::type Chris@16: operator/(const unit&,const quantity& rhs) Chris@16: { Chris@16: typedef typename divide_typeof_helper< unit,quantity >::type type; Chris@16: Chris@16: return type::from_value(Y(1)/rhs.value()); Chris@16: } Chris@16: Chris@16: /// runtime quantity times unit Chris@16: template Chris@16: inline Chris@16: typename multiply_typeof_helper< quantity,unit >::type Chris@16: operator*(const quantity& lhs,const unit&) Chris@16: { Chris@16: typedef typename multiply_typeof_helper< quantity,unit >::type type; Chris@16: Chris@16: return type::from_value(lhs.value()); Chris@16: } Chris@16: Chris@16: /// runtime quantity divided by unit Chris@16: template Chris@16: inline Chris@16: typename divide_typeof_helper< quantity,unit >::type Chris@16: operator/(const quantity& lhs,const unit&) Chris@16: { Chris@16: typedef typename divide_typeof_helper< quantity,unit >::type type; Chris@16: Chris@16: return type::from_value(lhs.value()); Chris@16: } Chris@16: Chris@16: /// runtime unary plus quantity Chris@16: template Chris@16: typename unary_plus_typeof_helper< quantity >::type Chris@16: operator+(const quantity& val) Chris@16: { Chris@16: typedef typename unary_plus_typeof_helper< quantity >::type type; Chris@16: Chris@16: return type::from_value(+val.value()); Chris@16: } Chris@16: Chris@16: /// runtime unary minus quantity Chris@16: template Chris@16: typename unary_minus_typeof_helper< quantity >::type Chris@16: operator-(const quantity& val) Chris@16: { Chris@16: typedef typename unary_minus_typeof_helper< quantity >::type type; Chris@16: Chris@16: return type::from_value(-val.value()); Chris@16: } Chris@16: Chris@16: /// runtime quantity plus quantity Chris@16: template Chris@16: inline Chris@16: typename add_typeof_helper< quantity,quantity >::type Chris@16: operator+(const quantity& lhs, Chris@16: const quantity& rhs) Chris@16: { Chris@16: typedef typename add_typeof_helper< quantity,quantity >::type type; Chris@16: Chris@16: return type::from_value(lhs.value()+rhs.value()); Chris@16: } Chris@16: Chris@16: /// runtime quantity minus quantity Chris@16: template Chris@16: inline Chris@16: typename subtract_typeof_helper< quantity,quantity >::type Chris@16: operator-(const quantity& lhs, Chris@16: const quantity& rhs) Chris@16: { Chris@16: typedef typename subtract_typeof_helper< quantity,quantity >::type type; Chris@16: Chris@16: return type::from_value(lhs.value()-rhs.value()); Chris@16: } Chris@16: Chris@16: /// runtime quantity times quantity Chris@16: template Chris@16: inline Chris@16: typename multiply_typeof_helper< quantity,quantity >::type Chris@16: operator*(const quantity& lhs, Chris@16: const quantity& rhs) Chris@16: { Chris@16: typedef typename multiply_typeof_helper< quantity, Chris@16: quantity >::type type; Chris@16: Chris@16: return type::from_value(lhs.value()*rhs.value()); Chris@16: } Chris@16: Chris@16: /// runtime quantity divided by quantity Chris@16: template Chris@16: inline Chris@16: typename divide_typeof_helper< quantity,quantity >::type Chris@16: operator/(const quantity& lhs, Chris@16: const quantity& rhs) Chris@16: { Chris@16: typedef typename divide_typeof_helper< quantity, Chris@16: quantity >::type type; Chris@16: Chris@16: return type::from_value(lhs.value()/rhs.value()); Chris@16: } Chris@16: Chris@16: /// runtime operator== Chris@16: template Chris@16: inline Chris@16: bool Chris@16: operator==(const quantity& val1, Chris@16: const quantity& val2) Chris@16: { Chris@16: return val1.value() == val2.value(); Chris@16: } Chris@16: Chris@16: /// runtime operator!= Chris@16: template Chris@16: inline Chris@16: bool Chris@16: operator!=(const quantity& val1, Chris@16: const quantity& val2) Chris@16: { Chris@16: return val1.value() != val2.value(); Chris@16: } Chris@16: Chris@16: /// runtime operator< Chris@16: template Chris@16: inline Chris@16: bool Chris@16: operator<(const quantity& val1, Chris@16: const quantity& val2) Chris@16: { Chris@16: return val1.value() < val2.value(); Chris@16: } Chris@16: Chris@16: /// runtime operator<= Chris@16: template Chris@16: inline Chris@16: bool Chris@16: operator<=(const quantity& val1, Chris@16: const quantity& val2) Chris@16: { Chris@16: return val1.value() <= val2.value(); Chris@16: } Chris@16: Chris@16: /// runtime operator> Chris@16: template Chris@16: inline Chris@16: bool Chris@16: operator>(const quantity& val1, Chris@16: const quantity& val2) Chris@16: { Chris@16: return val1.value() > val2.value(); Chris@16: } Chris@16: Chris@16: /// runtime operator>= Chris@16: template Chris@16: inline Chris@16: bool Chris@16: operator>=(const quantity& val1, Chris@16: const quantity& val2) Chris@16: { Chris@16: return val1.value() >= val2.value(); Chris@16: } Chris@16: Chris@16: } // namespace units Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_UNITS_QUANTITY_HPP