conversion.hpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Boost.Units - A C++ library for zero-overhead dimensional analysis and
  2. // unit/quantity manipulation and conversion
  3. //
  4. // Copyright (C) 2003-2008 Matthias Christian Schabel
  5. // Copyright (C) 2007-2008 Steven Watanabe
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See
  8. // accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_UNITS_CONVERSION_HPP
  11. #define BOOST_UNITS_CONVERSION_HPP
  12. /// \file
  13. /// \brief Template for defining conversions between quantities.
  14. #include <boost/units/detail/conversion_impl.hpp>
  15. namespace boost {
  16. namespace units {
  17. template<class From, class To>
  18. struct conversion_helper;
  19. #ifdef BOOST_UNITS_DOXYGEN
  20. /// Template for defining conversions between
  21. /// quantities. This template should be specialized
  22. /// for every quantity that allows conversions.
  23. /// For example, if you have a two units
  24. /// called pair and dozen you would write
  25. /// @code
  26. /// namespace boost {
  27. /// namespace units {
  28. /// template<class T0, class T1>
  29. /// struct conversion_helper<quantity<dozen, T0>, quantity<pair, T1> >
  30. /// {
  31. /// static quantity<pair, T1> convert(const quantity<dozen, T0>& source)
  32. /// {
  33. /// return(quantity<pair, T1>::from_value(6 * source.value()));
  34. /// }
  35. /// };
  36. /// }
  37. /// }
  38. /// @endcode
  39. ///
  40. /// In most cases, the predefined specializations for @c unit
  41. /// and @c absolute should be sufficient, so users should rarely
  42. /// need to use this.
  43. template<class From, class To>
  44. struct conversion_helper
  45. {
  46. static BOOST_CONSTEXPR To convert(const From&);
  47. };
  48. #endif
  49. /// Defines the conversion factor from a base unit to any unit
  50. /// or to another base unit with the correct dimensions. Uses
  51. /// of this macro must appear at global scope.
  52. /// If the destination unit is a base unit or a unit that contains
  53. /// only one base unit which is raised to the first power (e.g. feet->meters)
  54. /// the reverse (meters->feet in this example) need not be defined explicitly.
  55. #define BOOST_UNITS_DEFINE_CONVERSION_FACTOR(Source, Destination, type_, value_) \
  56. namespace boost { \
  57. namespace units { \
  58. template<> \
  59. struct select_base_unit_converter< \
  60. unscale<Source>::type, \
  61. unscale<reduce_unit<Destination::unit_type>::type>::type \
  62. > \
  63. { \
  64. typedef Source source_type; \
  65. typedef reduce_unit<Destination::unit_type>::type destination_type; \
  66. }; \
  67. template<> \
  68. struct base_unit_converter<Source, reduce_unit<Destination::unit_type>::type> \
  69. { \
  70. BOOST_STATIC_CONSTEXPR bool is_defined = true; \
  71. typedef type_ type; \
  72. static BOOST_CONSTEXPR type value() { return(value_); } \
  73. }; \
  74. } \
  75. } \
  76. void boost_units_require_semicolon()
  77. /// Defines the conversion factor from a base unit to any other base
  78. /// unit with the same dimensions. Params should be a Boost.Preprocessor
  79. /// Seq of template parameters, such as (class T1)(class T2)
  80. /// All uses of must appear at global scope. The reverse conversion will
  81. /// be defined automatically. This macro is a little dangerous, because,
  82. /// unlike the non-template form, it will silently fail if either base
  83. /// unit is scaled. This is probably not an issue if both the source
  84. /// and destination types depend on the template parameters, but be aware
  85. /// that a generic conversion to kilograms is not going to work.
  86. #define BOOST_UNITS_DEFINE_CONVERSION_FACTOR_TEMPLATE(Params, Source, Destination, type_, value_) \
  87. namespace boost { \
  88. namespace units { \
  89. template<BOOST_PP_SEQ_ENUM(Params)> \
  90. struct base_unit_converter< \
  91. Source, \
  92. BOOST_UNITS_MAKE_HETEROGENEOUS_UNIT(Destination, typename Source::dimension_type)\
  93. > \
  94. { \
  95. BOOST_STATIC_CONSTEXPR bool is_defined = true; \
  96. typedef type_ type; \
  97. static BOOST_CONSTEXPR type value() { return(value_); } \
  98. }; \
  99. } \
  100. } \
  101. void boost_units_require_semicolon()
  102. /// Specifies the default conversion to be applied when
  103. /// no direct conversion is available.
  104. /// Source is a base unit. Dest is any unit with the
  105. /// same dimensions.
  106. #define BOOST_UNITS_DEFAULT_CONVERSION(Source, Dest) \
  107. namespace boost { \
  108. namespace units { \
  109. template<> \
  110. struct unscaled_get_default_conversion<unscale<Source>::type> \
  111. { \
  112. BOOST_STATIC_CONSTEXPR bool is_defined = true; \
  113. typedef Dest::unit_type type; \
  114. }; \
  115. } \
  116. } \
  117. void boost_units_require_semicolon()
  118. /// Specifies the default conversion to be applied when
  119. /// no direct conversion is available.
  120. /// Params is a PP Sequence of template arguments.
  121. /// Source is a base unit. Dest is any unit with the
  122. /// same dimensions. The source must not be a scaled
  123. /// base unit.
  124. #define BOOST_UNITS_DEFAULT_CONVERSION_TEMPLATE(Params, Source, Dest) \
  125. namespace boost { \
  126. namespace units { \
  127. template<BOOST_PP_SEQ_ENUM(Params)> \
  128. struct unscaled_get_default_conversion<Source> \
  129. { \
  130. BOOST_STATIC_CONSTEXPR bool is_defined = true; \
  131. typedef typename Dest::unit_type type; \
  132. }; \
  133. } \
  134. } \
  135. void boost_units_require_semicolon()
  136. /// INTERNAL ONLY
  137. /// Users should not create their units in namespace boost::units.
  138. /// If we want to make this public it needs to allow better control over
  139. /// the namespaces. --SJW.
  140. /// template that defines a base_unit and conversion to another dimensionally-consistent unit
  141. #define BOOST_UNITS_DEFINE_BASE_UNIT_WITH_CONVERSIONS(namespace_, name_, name_string_, symbol_string_, factor, unit, id)\
  142. namespace boost { \
  143. namespace units { \
  144. namespace namespace_ { \
  145. struct name_ ## _base_unit \
  146. : base_unit<name_ ## _base_unit, unit::dimension_type, id> { \
  147. static BOOST_CONSTEXPR const char* name() { return(name_string_); } \
  148. static BOOST_CONSTEXPR const char* symbol() { return(symbol_string_); } \
  149. }; \
  150. } \
  151. } \
  152. } \
  153. BOOST_UNITS_DEFINE_CONVERSION_FACTOR(namespace_::name_ ## _base_unit, unit, double, factor); \
  154. BOOST_UNITS_DEFAULT_CONVERSION(namespace_::name_ ## _base_unit, unit)
  155. /// Find the conversion factor between two units.
  156. template<class FromUnit,class ToUnit>
  157. inline
  158. BOOST_CONSTEXPR
  159. typename one_to_double_type<
  160. typename detail::conversion_factor_helper<FromUnit, ToUnit>::type
  161. >::type
  162. conversion_factor(const FromUnit&,const ToUnit&)
  163. {
  164. return(one_to_double(detail::conversion_factor_helper<FromUnit, ToUnit>::value()));
  165. }
  166. } // namespace units
  167. } // namespace boost
  168. #endif // BOOST_UNITS_CONVERSION_HPP