Edit: /usr/include/boost/units/quantity.hpp (41860B)
// 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
#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;
BOOST_CONSTEXPR quantity() : val_()
{
BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
}
BOOST_CONSTEXPR quantity(unspecified_null_pointer_constant_type) : val_()
{
BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
}
BOOST_CONSTEXPR 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() { }
BOOST_CXX14_CONSTEXPR 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
BOOST_CONSTEXPR 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 BOOST_CONSTEXPR 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
BOOST_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR 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
BOOST_CONSTEXPR 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
BOOST_CONSTEXPR 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 BOOST_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR 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;
}
BOOST_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR this_type& operator-=(const quantity& source)
{
BOOST_STATIC_ASSERT((boost::is_same::type, Unit>::value));
val_ -= source.value();
return *this;
}
template
BOOST_CXX14_CONSTEXPR this_type& operator*=(const quantity& source)
{
BOOST_STATIC_ASSERT((boost::is_same::type, Unit>::value));
val_ *= source.value();
return *this;
}
template
BOOST_CXX14_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR this_type& operator/=(const value_type& source) { val_ /= source; return *this; }
/// Construct quantity directly from @c value_type (potentially dangerous).
static BOOST_CONSTEXPR this_type from_value(const value_type& val) { return this_type(val, 0); }
protected:
explicit BOOST_CONSTEXPR 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;
BOOST_CONSTEXPR quantity() : val_()
{
BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
}
/// construction from raw @c value_type is allowed
BOOST_CONSTEXPR quantity(value_type val) : val_(val)
{
BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
}
BOOST_CONSTEXPR quantity(const this_type& source) : val_(source.val_)
{
BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
}
//~quantity() { }
BOOST_CXX14_CONSTEXPR 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
BOOST_CONSTEXPR 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 BOOST_CONSTEXPR 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
BOOST_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR 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
BOOST_CONSTEXPR 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 BOOST_CONSTEXPR 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
BOOST_CONSTEXPR 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 BOOST_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR this_type& operator=(const quantity& source)
{
*this = this_type(source);
return *this;
}
#endif
/// implicit conversion to @c value_type is allowed
BOOST_CONSTEXPR operator value_type() const { return val_; }
BOOST_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR 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
BOOST_CXX14_CONSTEXPR this_type& operator/=(const value_type& val) { val_ /= val; return *this; }
/// Construct quantity directly from @c value_type.
static BOOST_CONSTEXPR 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;
BOOST_CONSTEXPR type operator()(quantity& source) const { return const_cast(source.value()); }
};
/// specialization for casting to the value type
template
struct quantity_cast_helper >
{
typedef Y type;
BOOST_CONSTEXPR type operator()(const quantity& source) const { return source.value(); }
};
} // namespace detail
/// quantity_cast provides mutating access to underlying quantity value_type
template
inline
BOOST_CONSTEXPR
X
quantity_cast(Y& source)
{
return detail::quantity_cast_helper()(source);
}
template
inline
BOOST_CONSTEXPR
X
quantity_cast(const Y& source)
{
return detail::quantity_cast_helper()(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