| // 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) 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_UNIT_HPP |
| #define BOOST_UNITS_UNIT_HPP |
| |
| #include <boost/static_assert.hpp> |
| #include <boost/mpl/bool.hpp> |
| #include <boost/mpl/assert.hpp> |
| #include <boost/type_traits/is_same.hpp> |
| |
| #include <boost/units/config.hpp> |
| #include <boost/units/dimension.hpp> |
| #include <boost/units/operators.hpp> |
| #include <boost/units/units_fwd.hpp> |
| #include <boost/units/homogeneous_system.hpp> |
| #include <boost/units/heterogeneous_system.hpp> |
| #include <boost/units/is_dimension_list.hpp> |
| #include <boost/units/reduce_unit.hpp> |
| #include <boost/units/static_rational.hpp> |
| |
| namespace boost { |
| |
| namespace units { |
| |
| /// class representing a model-dependent unit with no associated value |
| |
| /// (e.g. meters, Kelvin, feet, etc...) |
| template<class Dim,class System, class Enable> |
| class unit |
| { |
| public: |
| typedef unit<Dim, System> unit_type; |
| typedef unit<Dim,System> this_type; |
| typedef Dim dimension_type; |
| typedef System system_type; |
| |
| unit() { } |
| unit(const this_type&) { } |
| //~unit() { } |
| |
| this_type& operator=(const this_type&) { } |
| |
| // sun will ignore errors resulting from templates |
| // instantiated in the return type of a function. |
| // Make sure that we get an error anyway by putting. |
| // the check in the destructor. |
| #ifdef __SUNPRO_CC |
| ~unit() { |
| BOOST_MPL_ASSERT((detail::check_system<System, Dim>)); |
| BOOST_MPL_ASSERT((is_dimension_list<Dim>)); |
| } |
| #else |
| private: |
| BOOST_MPL_ASSERT((detail::check_system<System, Dim>)); |
| BOOST_MPL_ASSERT((is_dimension_list<Dim>)); |
| #endif |
| }; |
| |
| } |
| |
| } |
| |
| #if BOOST_UNITS_HAS_BOOST_TYPEOF |
| |
| #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() |
| |
| BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::unit, 2) |
| |
| #endif |
| |
| namespace boost { |
| |
| namespace units { |
| |
| /// Returns a unique type for every unit. |
| template<class Dim, class System> |
| struct reduce_unit<unit<Dim, System> > |
| { |
| typedef unit< |
| Dim, |
| typename detail::make_heterogeneous_system< |
| Dim, |
| System |
| >::type |
| > type; |
| }; |
| |
| /// INTERNAL ONLY |
| template<class S1,class S2> |
| struct is_implicitly_convertible : |
| boost::is_same<typename reduce_unit<S1>::type, typename reduce_unit<S2>::type> |
| { }; |
| |
| /// unit unary plus typeof helper |
| /// INTERNAL ONLY |
| template<class Dim,class System> |
| struct unary_plus_typeof_helper< unit<Dim,System> > |
| { |
| typedef unit<Dim,System> type; |
| }; |
| |
| /// unit unary minus typeof helper |
| /// INTERNAL ONLY |
| template<class Dim,class System> |
| struct unary_minus_typeof_helper< unit<Dim,System> > |
| { |
| typedef unit<Dim,System> type; |
| }; |
| |
| /// unit add typeof helper |
| /// INTERNAL ONLY |
| template<class Dim, |
| class System> |
| struct add_typeof_helper< unit<Dim,System>,unit<Dim,System> > |
| { |
| typedef unit<Dim,System> type; |
| }; |
| |
| /// unit subtract typeof helper |
| /// INTERNAL ONLY |
| template<class Dim, |
| class System> |
| struct subtract_typeof_helper< unit<Dim,System>,unit<Dim,System> > |
| { |
| typedef unit<Dim,System> type; |
| }; |
| |
| /// unit multiply typeof helper for two identical homogeneous systems |
| /// INTERNAL ONLY |
| template<class Dim1, |
| class Dim2, |
| class System> |
| struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System> >, |
| unit<Dim2,homogeneous_system<System> > > |
| { |
| typedef unit<typename mpl::times<Dim1,Dim2>::type,homogeneous_system<System> > type; |
| }; |
| |
| /// unit multiply typeof helper for two different homogeneous systems |
| /// INTERNAL ONLY |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System1> >, |
| unit<Dim2,homogeneous_system<System2> > > |
| { |
| typedef unit< |
| typename mpl::times<Dim1,Dim2>::type, |
| typename detail::multiply_systems< |
| typename detail::make_heterogeneous_system<Dim1, System1>::type, |
| typename detail::make_heterogeneous_system<Dim2, System2>::type |
| >::type |
| > type; |
| }; |
| |
| /// unit multiply typeof helper for a heterogeneous and a homogeneous system |
| /// INTERNAL ONLY |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| struct multiply_typeof_helper< unit<Dim1,heterogeneous_system<System1> >, |
| unit<Dim2,homogeneous_system<System2> > > |
| { |
| typedef unit< |
| typename mpl::times<Dim1,Dim2>::type, |
| typename detail::multiply_systems< |
| heterogeneous_system<System1>, |
| typename detail::make_heterogeneous_system<Dim2, System2>::type |
| >::type |
| > type; |
| }; |
| |
| /// unit multiply typeof helper for a homogeneous and a heterogeneous system |
| /// INTERNAL ONLY |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System1> >, |
| unit<Dim2,heterogeneous_system<System2> > > |
| { |
| typedef unit< |
| typename mpl::times<Dim1,Dim2>::type, |
| typename detail::multiply_systems< |
| typename detail::make_heterogeneous_system<Dim1, System1>::type, |
| heterogeneous_system<System2> |
| >::type |
| > type; |
| }; |
| |
| /// unit multiply typeof helper for two heterogeneous systems |
| /// INTERNAL ONLY |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| struct multiply_typeof_helper< unit<Dim1,heterogeneous_system<System1> >, |
| unit<Dim2,heterogeneous_system<System2> > > |
| { |
| typedef unit< |
| typename mpl::times<Dim1,Dim2>::type, |
| typename detail::multiply_systems< |
| heterogeneous_system<System1>, |
| heterogeneous_system<System2> |
| >::type |
| > type; |
| }; |
| |
| /// unit divide typeof helper for two identical homogeneous systems |
| /// INTERNAL ONLY |
| template<class Dim1, |
| class Dim2, |
| class System> |
| struct divide_typeof_helper< unit<Dim1,homogeneous_system<System> >, |
| unit<Dim2,homogeneous_system<System> > > |
| { |
| typedef unit<typename mpl::divides<Dim1,Dim2>::type,homogeneous_system<System> > type; |
| }; |
| |
| /// unit divide typeof helper for two different homogeneous systems |
| /// INTERNAL ONLY |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| struct divide_typeof_helper< unit<Dim1,homogeneous_system<System1> >, |
| unit<Dim2,homogeneous_system<System2> > > |
| { |
| typedef unit< |
| typename mpl::divides<Dim1,Dim2>::type, |
| typename detail::divide_systems< |
| typename detail::make_heterogeneous_system<Dim1, System1>::type, |
| typename detail::make_heterogeneous_system<Dim2, System2>::type |
| >::type |
| > type; |
| }; |
| |
| /// unit divide typeof helper for a heterogeneous and a homogeneous system |
| /// INTERNAL ONLY |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| struct divide_typeof_helper< unit<Dim1,heterogeneous_system<System1> >, |
| unit<Dim2,homogeneous_system<System2> > > |
| { |
| typedef unit< |
| typename mpl::divides<Dim1,Dim2>::type, |
| typename detail::divide_systems< |
| heterogeneous_system<System1>, |
| typename detail::make_heterogeneous_system<Dim2, System2>::type |
| >::type |
| > type; |
| }; |
| |
| /// unit divide typeof helper for a homogeneous and a heterogeneous system |
| /// INTERNAL ONLY |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| struct divide_typeof_helper< unit<Dim1,homogeneous_system<System1> >, |
| unit<Dim2,heterogeneous_system<System2> > > |
| { |
| typedef unit< |
| typename mpl::divides<Dim1,Dim2>::type, |
| typename detail::divide_systems< |
| typename detail::make_heterogeneous_system<Dim1, System1>::type, |
| heterogeneous_system<System2> |
| >::type |
| > type; |
| }; |
| |
| /// unit divide typeof helper for two heterogeneous systems |
| /// INTERNAL ONLY |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| struct divide_typeof_helper< unit<Dim1,heterogeneous_system<System1> >, |
| unit<Dim2,heterogeneous_system<System2> > > |
| { |
| typedef unit< |
| typename mpl::divides<Dim1,Dim2>::type, |
| typename detail::divide_systems< |
| heterogeneous_system<System1>, |
| heterogeneous_system<System2> |
| >::type |
| > type; |
| }; |
| |
| /// raise unit to a @c static_rational power |
| template<class Dim,class System,long N,long D> |
| struct power_typeof_helper<unit<Dim,System>,static_rational<N,D> > |
| { |
| typedef unit<typename static_power<Dim,static_rational<N,D> >::type,typename static_power<System, static_rational<N,D> >::type> type; |
| |
| static type value(const unit<Dim,System>&) |
| { |
| return type(); |
| } |
| }; |
| |
| /// take the @c static_rational root of a unit |
| template<class Dim,class System,long N,long D> |
| struct root_typeof_helper<unit<Dim,System>,static_rational<N,D> > |
| { |
| typedef unit<typename static_root<Dim,static_rational<N,D> >::type,typename static_root<System, static_rational<N,D> >::type> type; |
| |
| static type value(const unit<Dim,System>&) |
| { |
| return type(); |
| } |
| }; |
| |
| /// unit runtime unary plus |
| template<class Dim,class System> |
| typename unary_plus_typeof_helper< unit<Dim,System> >::type |
| operator+(const unit<Dim,System>&) |
| { |
| typedef typename unary_plus_typeof_helper< unit<Dim,System> >::type type; |
| |
| return type(); |
| } |
| |
| /// unit runtime unary minus |
| template<class Dim,class System> |
| typename unary_minus_typeof_helper< unit<Dim,System> >::type |
| operator-(const unit<Dim,System>&) |
| { |
| typedef typename unary_minus_typeof_helper< unit<Dim,System> >::type type; |
| |
| return type(); |
| } |
| |
| /// runtime add two units |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| typename add_typeof_helper< unit<Dim1,System1>, |
| unit<Dim2,System2> >::type |
| operator+(const unit<Dim1,System1>&,const unit<Dim2,System2>&) |
| { |
| BOOST_STATIC_ASSERT((boost::is_same<System1,System2>::value == true)); |
| |
| typedef System1 system_type; |
| typedef typename add_typeof_helper< unit<Dim1,system_type>, |
| unit<Dim2,system_type> >::type type; |
| |
| return type(); |
| } |
| |
| /// runtime subtract two units |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| typename subtract_typeof_helper< unit<Dim1,System1>, |
| unit<Dim2,System2> >::type |
| operator-(const unit<Dim1,System1>&,const unit<Dim2,System2>&) |
| { |
| BOOST_STATIC_ASSERT((boost::is_same<System1,System2>::value == true)); |
| |
| typedef System1 system_type; |
| typedef typename subtract_typeof_helper< unit<Dim1,system_type>, |
| unit<Dim2,system_type> >::type type; |
| |
| return type(); |
| } |
| |
| /// runtime multiply two units |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| typename multiply_typeof_helper< unit<Dim1,System1>, |
| unit<Dim2,System2> >::type |
| operator*(const unit<Dim1,System1>&,const unit<Dim2,System2>&) |
| { |
| typedef typename multiply_typeof_helper< unit<Dim1,System1>, |
| unit<Dim2,System2> >::type type; |
| |
| return type(); |
| } |
| |
| /// runtime divide two units |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| typename divide_typeof_helper< unit<Dim1,System1>, |
| unit<Dim2,System2> >::type |
| operator/(const unit<Dim1,System1>&,const unit<Dim2,System2>&) |
| { |
| typedef typename divide_typeof_helper< unit<Dim1,System1>, |
| unit<Dim2,System2> >::type type; |
| |
| return type(); |
| } |
| |
| /// unit runtime @c operator== |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| inline |
| bool |
| operator==(const unit<Dim1,System1>&,const unit<Dim2,System2>&) |
| { |
| return boost::is_same<typename reduce_unit<unit<Dim1,System1> >::type, typename reduce_unit<unit<Dim2,System2> >::type>::value; |
| } |
| |
| /// unit runtime @c operator!= |
| template<class Dim1, |
| class Dim2, |
| class System1, |
| class System2> |
| inline |
| bool |
| operator!=(const unit<Dim1,System1>&,const unit<Dim2,System2>&) |
| { |
| return !boost::is_same<typename reduce_unit<unit<Dim1,System1> >::type, typename reduce_unit<unit<Dim2,System2> >::type>::value; |
| } |
| |
| } // namespace units |
| |
| } // namespace boost |
| |
| #endif // BOOST_UNITS_UNIT_HPP |