441 lines
13 KiB
C++
441 lines
13 KiB
C++
|
// 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&) { return *this; }
|
||
|
|
||
|
// 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
|