|
Boost-Commit : |
From: steven_watanabe_at_[hidden]
Date: 2007-05-30 15:43:53
Author: steven_watanabe
Date: 2007-05-30 15:43:52 EDT (Wed, 30 May 2007)
New Revision: 4368
URL: http://svn.boost.org/trac/boost/changeset/4368
Log:
Fixed obscure heterogeneous_system bug
Text files modified:
sandbox/units/boost/units/conversion.hpp | 48 ++++++++++++++++++++++++++++
sandbox/units/boost/units/heterogeneous_system.hpp | 66 +++++++++++++++++++++++++++++++++++++++
sandbox/units/boost/units/io.hpp | 12 +++++-
3 files changed, 121 insertions(+), 5 deletions(-)
Modified: sandbox/units/boost/units/conversion.hpp
==============================================================================
--- sandbox/units/boost/units/conversion.hpp (original)
+++ sandbox/units/boost/units/conversion.hpp 2007-05-30 15:43:52 EDT (Wed, 30 May 2007)
@@ -37,12 +37,42 @@
template<class From, class To>
struct conversion_helper;
+#ifdef BOOST_UNITS_DOXYGEN
+
+/// Template for defining conversions between
+/// quanties. This template should be specialized
+/// for every quantity that allows conversions.
+/// For example, if you have a two units
+/// called pair and dozen you would write
+/// @code
+/// namespace boost {
+/// namespace units {
+/// template<class T0, class T1>
+/// struct conversion_helper<quantity<dozen, T0>, quantity<pair, T1> >
+/// {
+/// static quantity<pair, T1> convert(const quantity<dozen, T0>& source)
+/// {
+/// return(quantity<pair, T1>::from_value(6 * source.value()));
+/// }
+/// };
+/// }
+/// }
+/// @endcode
+template<class From, class To>
+struct conversion_helper {
+ static To convert(const From&);
+};
+
+#endif
+
+/// INTERNAL ONLY
template<class Source, class Destination>
struct select_base_unit_converter {
typedef Source source_type;
typedef Destination destination_type;
};
+/// INTERNAL ONLY
template<class Source, class Destination>
struct base_unit_converter {
typedef select_base_unit_converter<typename unscale<Source>::type, typename unscale<Destination>::type> selector;
@@ -59,6 +89,8 @@
}
};
+namespace detail {
+
template<bool try_inverse, bool trivial>
struct inverse_base_unit_converter_impl;
@@ -109,6 +141,9 @@
(boost::is_same<typename Dest::unit_type, typename selector::destination_type>::value) };
};
+}
+
+/// INTERNAL ONLY
template<class Source, class Dest>
struct base_unit_converter<
Source,
@@ -121,7 +156,7 @@
>
>
>
-> : inverse_base_unit_converter_impl<use_inverse_conversion<Source, Dest>::value, boost::is_same<Source, Dest>::value>::template apply<Source, Dest> {
+> : detail::inverse_base_unit_converter_impl<detail::use_inverse_conversion<Source, Dest>::value, boost::is_same<Source, Dest>::value>::template apply<Source, Dest> {
};
#define BOOST_UNITS_DEFINE_CONVERSION(Source, Destination, type_, value_)\
@@ -172,10 +207,14 @@
} // namespace detail
+/// conversions between homogeneous systems are defined
template<class D, class L1, class T1, class L2, class T2>
struct conversion_helper<quantity<unit<D, homogeneous_system<L1> >, T1>, quantity<unit<D, homogeneous_system<L2> >, T2> > {
+ /// INTERNAL ONLY
typedef quantity<unit<D, homogeneous_system<L2> >, T2> destination_type;
+ /// INTERNAL ONLY
typedef typename reduce_unit<unit<D, homogeneous_system<L1> > >::type source_unit;
+ /// INTERNAL ONLY
typedef typename source_unit::system_type::type unit_list;
static destination_type convert(const quantity<unit<D, homogeneous_system<L1> >, T1>& source) {
return(destination_type::from_value(source.value() *
@@ -187,8 +226,10 @@
}
};
+/// conversions between heterogeneous systems and homogeneous systems are defined
template<class D, class L1, class T1, class L2, class T2>
struct conversion_helper<quantity<unit<D, heterogeneous_system<L1> >, T1>, quantity<unit<D, homogeneous_system<L2> >, T2> > {
+ /// INTERNAL ONLY
typedef quantity<unit<D, homogeneous_system<L2> >, T2> destination_type;
static destination_type convert(const quantity<unit<D, heterogeneous_system<L1> >, T1>& source) {
return(destination_type::from_value(source.value() *
@@ -203,8 +244,10 @@
// There is no simple algorithm for doing this conversion
// other than just defining it as the reverse of the
// heterogeneous->homogeneous case
+/// conversions between heterogeneous systems and homogeneous systems are defined
template<class D, class L1, class T1, class L2, class T2>
struct conversion_helper<quantity<unit<D, homogeneous_system<L1> >, T1>, quantity<unit<D, heterogeneous_system<L2> >, T2> > {
+ /// INTERNAL ONLY
typedef quantity<unit<D, heterogeneous_system<L2> >, T2> destination_type;
static destination_type convert(const quantity<unit<D, homogeneous_system<L1> >, T1>& source) {
return(destination_type::from_value(source.value() /
@@ -264,6 +307,7 @@
}
+/// Find the conversion factor between two units.
template<class FromUnit,class ToUnit>
inline
typename detail::conversion_factor_helper<FromUnit, ToUnit>::type
@@ -272,6 +316,8 @@
return(detail::conversion_factor_helper<FromUnit, ToUnit>::value());
}
+/// Find the conversion factor between two units with an explicit return type.
+/// e.g. conversion_factor<int>(newton, dyne) returns 100000
template<class Y, class FromUnit,class ToUnit>
inline
Y
Modified: sandbox/units/boost/units/heterogeneous_system.hpp
==============================================================================
--- sandbox/units/boost/units/heterogeneous_system.hpp (original)
+++ sandbox/units/boost/units/heterogeneous_system.hpp 2007-05-30 15:43:52 EDT (Wed, 30 May 2007)
@@ -45,18 +45,26 @@
}
+/// INTERNAL ONLY
template<class L, class Dimensions>
struct heterogeneous_system_pair {
typedef L type;
typedef Dimensions dimensions;
};
+/// A system that can represent any possible combination
+/// of units at the expense of not preserving information
+/// about how it was created. Do not create specializations
+/// of this template directly. Instead use reduce_unit and
+/// base_unit<...>::unit_type.
template<class T>
struct heterogeneous_system : T {
};
+/// INTERNAL ONLY
struct heterogeneous_system_dim_tag {};
+/// INTERNAL ONLY
template<class Unit, class Exponent>
struct heterogeneous_system_dim {
typedef heterogeneous_system_dim_tag tag;
@@ -81,6 +89,7 @@
namespace mpl {
+/// INTERNAL ONLY
template<>
struct plus_impl<boost::units::heterogeneous_system_dim_tag, boost::units::heterogeneous_system_dim_tag> {
template<class T0, class T1>
@@ -92,6 +101,7 @@
};
};
+/// INTERNAL ONLY
template<>
struct times_impl<boost::units::heterogeneous_system_dim_tag, boost::units::detail::static_rational_tag> {
template<class T0, class T1>
@@ -103,6 +113,7 @@
};
};
+/// INTERNAL ONLY
template<>
struct negate_impl<boost::units::heterogeneous_system_dim_tag> {
template<class T>
@@ -176,6 +187,7 @@
} // namespace detail
+/// INTERNAL ONLY
template<class S, long N, long D>
struct static_power<heterogeneous_system<S>, static_rational<N,D> > {
typedef heterogeneous_system<
@@ -186,6 +198,7 @@
> type;
};
+/// INTERNAL ONLY
template<class S, long N, long D>
struct static_root<heterogeneous_system<S>, static_rational<N,D> > {
typedef heterogeneous_system<
@@ -196,6 +209,7 @@
> type;
};
+/// Returns a unique type for every unit.
template<class Unit>
struct reduce_unit {
typedef unit<
@@ -209,11 +223,54 @@
namespace detail {
+/// add an instantiation of dim to Sequence.
+template<bool>
+struct push_front_or_add_impl;
+
+template<>
+struct push_front_or_add_impl<true>
+{
+ template<typename Sequence, typename T>
+ struct apply
+ {
+ typedef typename mpl::plus<T, typename mpl::front<Sequence>::type>::type item;
+ typedef typename push_front_if<!is_empty_dim<item>::value>::template apply<
+ typename mpl::pop_front<Sequence>::type,
+ item
+ > type;
+ };
+};
+
+template<>
+struct push_front_or_add_impl<false>
+{
+ template<typename Sequence, typename T>
+ struct apply
+ {
+ typedef typename mpl::push_front<Sequence, T>::type type;
+ };
+};
+
+template<typename Sequence, typename T>
+struct push_front_or_add
+{
+ typedef typename push_front_or_add_impl<boost::is_same<typename T::tag_type, typename mpl::front<Sequence>::type::tag_type>::value>::template apply<
+ Sequence,
+ T
+ >::type type;
+};
+
+template<typename T>
+struct push_front_or_add<dimensionless_type, T>
+{
+ typedef typename mpl::push_front<dimensionless_type, T>::type type;
+};
+
template<int N>
struct unscale_heterogeneous_system_impl {
template<class Begin>
struct apply {
- typedef typename mpl::push_front<
+ typedef typename push_front_or_add<
typename unscale_heterogeneous_system_impl<N-1>::template apply<
typename mpl::next<Begin>::type
>::type,
@@ -232,6 +289,10 @@
}
+/// Unscale all the base units. e.g
+/// km s -> m s
+/// cm km -> m^2
+/// INTERNAL ONLY
template<class T>
struct unscale<heterogeneous_system<T> > {
typedef heterogeneous_system<
@@ -246,6 +307,7 @@
> type;
};
+/// INTERNAL ONLY
template<class Unit, class Exponent>
struct unscale<heterogeneous_system_dim<Unit, Exponent> > {
typedef heterogeneous_system_dim<typename unscale<Unit>::type, Exponent> type;
@@ -276,6 +338,7 @@
} // namespace detail
+/// INTERNAL ONLY
template<class T>
struct get_scale_list<heterogeneous_system<T> > {
typedef typename detail::get_scale_list_of_heterogeneous_system_impl<
@@ -283,6 +346,7 @@
>::template apply<typename T::type>::type type;
};
+/// INTERNAL ONLY
template<class Unit, class Exponent>
struct get_scale_list<heterogeneous_system_dim<Unit, Exponent> > {
typedef typename static_power<typename get_scale_list<Unit>::type, Exponent>::type type;
Modified: sandbox/units/boost/units/io.hpp
==============================================================================
--- sandbox/units/boost/units/io.hpp (original)
+++ sandbox/units/boost/units/io.hpp 2007-05-30 15:43:52 EDT (Wed, 30 May 2007)
@@ -63,13 +63,16 @@
template<class T>
struct heterogeneous_system;
-template<class T>
+/// traits template for unit names
+template<class BaseUnit>
struct base_unit_info {
+ /// The full name of the unit (returns BaseUnit::name() by default)
static std::string name() {
- return(T::name());
+ return(BaseUnit::name());
}
+ /// The symbol for the base unit (Returns BaseUnit::symbol() by default)
static std::string symbol() {
- return(T::symbol());
+ return(BaseUnit::symbol());
}
};
@@ -130,12 +133,14 @@
} // namespace detail
+/// Print an @c unit as a list of base units and exponents e.g "m s^-1"
template<class Char, class Traits, class Dimension, class System>
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, const unit<Dimension, System>&) {
os << typename reduce_unit<unit<Dimension, System> >::type();
return(os);
}
+/// INTERNAL ONLY
template<class Char, class Traits, class Dimension, class System>
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, const unit<Dimension, heterogeneous_system<System> >&) {
detail::print_impl<mpl::size<typename System::type>::value>::template apply<
@@ -144,6 +149,7 @@
return(os);
}
+/// Print a @c quantity. Prints the value followed by the unit
template<class Char, class Traits, class Unit, class T>
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& os, const quantity<Unit, T>& q) {
os << q.value() << ' ' << Unit();
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk