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