Boost logo

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