$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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();