quantity.hpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219
  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_QUANTITY_HPP
  11. #define BOOST_UNITS_QUANTITY_HPP
  12. #include <algorithm>
  13. #include <boost/config.hpp>
  14. #include <boost/static_assert.hpp>
  15. #include <boost/mpl/bool.hpp>
  16. #include <boost/mpl/and.hpp>
  17. #include <boost/mpl/not.hpp>
  18. #include <boost/mpl/or.hpp>
  19. #include <boost/mpl/assert.hpp>
  20. #include <boost/utility/enable_if.hpp>
  21. #include <boost/type_traits/is_arithmetic.hpp>
  22. #include <boost/type_traits/is_convertible.hpp>
  23. #include <boost/type_traits/is_integral.hpp>
  24. #include <boost/type_traits/is_same.hpp>
  25. #include <boost/units/conversion.hpp>
  26. #include <boost/units/dimensionless_type.hpp>
  27. #include <boost/units/homogeneous_system.hpp>
  28. #include <boost/units/operators.hpp>
  29. #include <boost/units/static_rational.hpp>
  30. #include <boost/units/units_fwd.hpp>
  31. #include <boost/units/detail/dimensionless_unit.hpp>
  32. namespace boost {
  33. namespace units {
  34. namespace detail {
  35. template<class T, class Enable = void>
  36. struct is_base_unit : mpl::false_ {};
  37. template<class T>
  38. struct is_base_unit<T, typename T::boost_units_is_base_unit_type> : mpl::true_ {};
  39. template<class Source, class Destination>
  40. struct is_narrowing_conversion_impl : mpl::bool_<(sizeof(Source) > sizeof(Destination))> {};
  41. template<class Source, class Destination>
  42. struct is_non_narrowing_conversion :
  43. mpl::and_<
  44. boost::is_convertible<Source, Destination>,
  45. mpl::not_<
  46. mpl::and_<
  47. boost::is_arithmetic<Source>,
  48. boost::is_arithmetic<Destination>,
  49. mpl::or_<
  50. mpl::and_<
  51. is_integral<Destination>,
  52. mpl::not_<is_integral<Source> >
  53. >,
  54. is_narrowing_conversion_impl<Source, Destination>
  55. >
  56. >
  57. >
  58. >
  59. {};
  60. template<>
  61. struct is_non_narrowing_conversion<long double, double> : mpl::false_ {};
  62. // msvc 7.1 needs extra disambiguation
  63. template<class T, class U>
  64. struct disable_if_is_same
  65. {
  66. typedef void type;
  67. };
  68. template<class T>
  69. struct disable_if_is_same<T, T> {};
  70. }
  71. /// class declaration
  72. template<class Unit,class Y = double>
  73. class quantity
  74. {
  75. // base units are not the same as units.
  76. BOOST_MPL_ASSERT_NOT((detail::is_base_unit<Unit>));
  77. enum { force_instantiation_of_unit = sizeof(Unit) };
  78. typedef void (quantity::*unspecified_null_pointer_constant_type)(int*******);
  79. public:
  80. typedef quantity<Unit,Y> this_type;
  81. typedef Y value_type;
  82. typedef Unit unit_type;
  83. quantity() : val_()
  84. {
  85. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  86. }
  87. quantity(unspecified_null_pointer_constant_type) : val_()
  88. {
  89. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  90. }
  91. quantity(const this_type& source) : val_(source.val_)
  92. {
  93. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  94. }
  95. // Need to make sure that the destructor of
  96. // Unit which contains the checking is instantiated,
  97. // on sun.
  98. #ifdef __SUNPRO_CC
  99. ~quantity() {
  100. unit_type force_unit_instantiation;
  101. }
  102. #endif
  103. //~quantity() { }
  104. this_type& operator=(const this_type& source)
  105. {
  106. val_ = source.val_;
  107. return *this;
  108. }
  109. #ifndef BOOST_NO_SFINAE
  110. /// implicit conversion between value types is allowed if allowed for value types themselves
  111. template<class YY>
  112. quantity(const quantity<Unit,YY>& source,
  113. typename boost::enable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
  114. val_(source.value())
  115. {
  116. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  117. }
  118. /// implicit conversion between value types is not allowed if not allowed for value types themselves
  119. template<class YY>
  120. explicit quantity(const quantity<Unit,YY>& source,
  121. typename boost::disable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
  122. val_(static_cast<Y>(source.value()))
  123. {
  124. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  125. }
  126. #else
  127. /// implicit conversion between value types is allowed if allowed for value types themselves
  128. template<class YY>
  129. quantity(const quantity<Unit,YY>& source) :
  130. val_(source.value())
  131. {
  132. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  133. BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
  134. }
  135. #endif
  136. /// implicit assignment between value types is allowed if allowed for value types themselves
  137. template<class YY>
  138. this_type& operator=(const quantity<Unit,YY>& source)
  139. {
  140. BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
  141. *this = this_type(source);
  142. return *this;
  143. }
  144. #ifndef BOOST_NO_SFINAE
  145. /// explicit conversion between different unit systems is allowed if implicit conversion is disallowed
  146. template<class Unit2,class YY>
  147. explicit
  148. quantity(const quantity<Unit2,YY>& source,
  149. typename boost::disable_if<
  150. mpl::and_<
  151. //is_implicitly_convertible should be undefined when the
  152. //units are not convertible at all
  153. typename is_implicitly_convertible<Unit2,Unit>::type,
  154. detail::is_non_narrowing_conversion<YY, Y>
  155. >,
  156. typename detail::disable_if_is_same<Unit, Unit2>::type
  157. >::type* = 0)
  158. : val_(conversion_helper<quantity<Unit2,YY>,this_type>::convert(source).value())
  159. {
  160. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  161. BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
  162. }
  163. /// implicit conversion between different unit systems is allowed if each fundamental dimension is implicitly convertible
  164. template<class Unit2,class YY>
  165. quantity(const quantity<Unit2,YY>& source,
  166. typename boost::enable_if<
  167. mpl::and_<
  168. typename is_implicitly_convertible<Unit2,Unit>::type,
  169. detail::is_non_narrowing_conversion<YY, Y>
  170. >,
  171. typename detail::disable_if_is_same<Unit, Unit2>::type
  172. >::type* = 0)
  173. : val_(conversion_helper<quantity<Unit2,YY>,this_type>::convert(source).value())
  174. {
  175. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  176. BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
  177. }
  178. #else
  179. /// without SFINAE we can't distinguish between explicit and implicit conversions so
  180. /// the conversion is always explicit
  181. template<class Unit2,class YY>
  182. explicit quantity(const quantity<Unit2,YY>& source)
  183. : val_(conversion_helper<quantity<Unit2,YY>,this_type>::convert(source).value())
  184. {
  185. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  186. BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
  187. }
  188. #endif
  189. /// implicit assignment between different unit systems is allowed if each fundamental dimension is implicitly convertible
  190. template<class Unit2,class YY>
  191. this_type& operator=(const quantity<Unit2,YY>& source)
  192. {
  193. BOOST_STATIC_ASSERT((is_implicitly_convertible<Unit2,unit_type>::value == true));
  194. BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
  195. *this = this_type(source);
  196. return *this;
  197. }
  198. const value_type& value() const { return val_; } ///< constant accessor to value
  199. ///< can add a quantity of the same type if add_typeof_helper<value_type,value_type>::type is convertible to value_type
  200. template<class Unit2, class YY>
  201. this_type& operator+=(const quantity<Unit2, YY>& source)
  202. {
  203. BOOST_STATIC_ASSERT((boost::is_same<typename add_typeof_helper<Unit, Unit2>::type, Unit>::value));
  204. val_ += source.value();
  205. return *this;
  206. }
  207. ///< can subtract a quantity of the same type if subtract_typeof_helper<value_type,value_type>::type is convertible to value_type
  208. template<class Unit2, class YY>
  209. this_type& operator-=(const quantity<Unit2, YY>& source)
  210. {
  211. BOOST_STATIC_ASSERT((boost::is_same<typename subtract_typeof_helper<Unit, Unit2>::type, Unit>::value));
  212. val_ -= source.value();
  213. return *this;
  214. }
  215. template<class Unit2, class YY>
  216. this_type& operator*=(const quantity<Unit2, YY>& source)
  217. {
  218. BOOST_STATIC_ASSERT((boost::is_same<typename multiply_typeof_helper<Unit, Unit2>::type, Unit>::value));
  219. val_ *= source.value();
  220. return *this;
  221. }
  222. template<class Unit2, class YY>
  223. this_type& operator/=(const quantity<Unit2, YY>& source)
  224. {
  225. BOOST_STATIC_ASSERT((boost::is_same<typename divide_typeof_helper<Unit, Unit2>::type, Unit>::value));
  226. val_ /= source.value();
  227. return *this;
  228. }
  229. ///< can multiply a quantity by a scalar value_type if multiply_typeof_helper<value_type,value_type>::type is convertible to value_type
  230. this_type& operator*=(const value_type& source) { val_ *= source; return *this; }
  231. ///< can divide a quantity by a scalar value_type if divide_typeof_helper<value_type,value_type>::type is convertible to value_type
  232. this_type& operator/=(const value_type& source) { val_ /= source; return *this; }
  233. /// Construct quantity directly from @c value_type (potentially dangerous).
  234. static this_type from_value(const value_type& val) { return this_type(val, 0); }
  235. protected:
  236. explicit quantity(const value_type& val, int) : val_(val) { }
  237. private:
  238. value_type val_;
  239. };
  240. /// Specialization for dimensionless quantities. Implicit conversions between
  241. /// unit systems are allowed because all dimensionless quantities are equivalent.
  242. /// Implicit construction and assignment from and conversion to @c value_type is
  243. /// also allowed.
  244. template<class System,class Y>
  245. class quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(System),Y>
  246. {
  247. public:
  248. typedef quantity<unit<dimensionless_type,System>,Y> this_type;
  249. typedef Y value_type;
  250. typedef System system_type;
  251. typedef dimensionless_type dimension_type;
  252. typedef unit<dimension_type,system_type> unit_type;
  253. quantity() : val_()
  254. {
  255. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  256. }
  257. /// construction from raw @c value_type is allowed
  258. quantity(value_type val) : val_(val)
  259. {
  260. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  261. }
  262. quantity(const this_type& source) : val_(source.val_)
  263. {
  264. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  265. }
  266. //~quantity() { }
  267. this_type& operator=(const this_type& source)
  268. {
  269. val_ = source.val_;
  270. return *this;
  271. }
  272. #ifndef BOOST_NO_SFINAE
  273. /// implicit conversion between value types is allowed if allowed for value types themselves
  274. template<class YY>
  275. quantity(const quantity<unit<dimension_type,system_type>,YY>& source,
  276. typename boost::enable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
  277. val_(source.value())
  278. {
  279. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  280. }
  281. /// implicit conversion between value types is not allowed if not allowed for value types themselves
  282. template<class YY>
  283. explicit quantity(const quantity<unit<dimension_type,system_type>,YY>& source,
  284. typename boost::disable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
  285. val_(static_cast<Y>(source.value()))
  286. {
  287. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  288. }
  289. #else
  290. /// implicit conversion between value types is allowed if allowed for value types themselves
  291. template<class YY>
  292. quantity(const quantity<unit<dimension_type,system_type>,YY>& source) :
  293. val_(source.value())
  294. {
  295. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  296. BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
  297. }
  298. #endif
  299. /// implicit assignment between value types is allowed if allowed for value types themselves
  300. template<class YY>
  301. this_type& operator=(const quantity<unit<dimension_type,system_type>,YY>& source)
  302. {
  303. BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
  304. *this = this_type(source);
  305. return *this;
  306. }
  307. #if 1
  308. /// implicit conversion between different unit systems is allowed
  309. template<class System2, class Y2>
  310. quantity(const quantity<unit<dimensionless_type, System2>,Y2>& source,
  311. #ifdef __SUNPRO_CC
  312. typename boost::enable_if<
  313. boost::mpl::and_<
  314. detail::is_non_narrowing_conversion<Y2, Y>,
  315. detail::is_dimensionless_system<System2>
  316. >
  317. >::type* = 0
  318. #else
  319. typename boost::enable_if<detail::is_non_narrowing_conversion<Y2, Y> >::type* = 0,
  320. typename detail::disable_if_is_same<System, System2>::type* = 0,
  321. typename boost::enable_if<detail::is_dimensionless_system<System2> >::type* = 0
  322. #endif
  323. ) :
  324. val_(source.value())
  325. {
  326. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  327. }
  328. /// implicit conversion between different unit systems is allowed
  329. template<class System2, class Y2>
  330. explicit quantity(const quantity<unit<dimensionless_type, System2>,Y2>& source,
  331. #ifdef __SUNPRO_CC
  332. typename boost::enable_if<
  333. boost::mpl::and_<
  334. boost::mpl::not_<detail::is_non_narrowing_conversion<Y2, Y> >,
  335. detail::is_dimensionless_system<System2>
  336. >
  337. >::type* = 0
  338. #else
  339. typename boost::disable_if<detail::is_non_narrowing_conversion<Y2, Y> >::type* = 0,
  340. typename detail::disable_if_is_same<System, System2>::type* = 0,
  341. typename boost::enable_if<detail::is_dimensionless_system<System2> >::type* = 0
  342. #endif
  343. ) :
  344. val_(static_cast<Y>(source.value()))
  345. {
  346. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  347. }
  348. #else
  349. /// implicit conversion between different unit systems is allowed
  350. template<class System2, class Y2>
  351. quantity(const quantity<unit<dimensionless_type,homogeneous_system<System2> >,Y2>& source) :
  352. val_(source.value())
  353. {
  354. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  355. BOOST_STATIC_ASSERT((boost::is_convertible<Y2, Y>::value == true));
  356. }
  357. #endif
  358. /// conversion between different unit systems is explicit when
  359. /// the units are not equivalent.
  360. template<class System2, class Y2>
  361. explicit quantity(const quantity<unit<dimensionless_type, System2>,Y2>& source,
  362. typename boost::disable_if<detail::is_dimensionless_system<System2> >::type* = 0) :
  363. val_(conversion_helper<quantity<unit<dimensionless_type, System2>,Y2>, this_type>::convert(source).value())
  364. {
  365. BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
  366. }
  367. #ifndef __SUNPRO_CC
  368. /// implicit assignment between different unit systems is allowed
  369. template<class System2>
  370. this_type& operator=(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(System2),Y>& source)
  371. {
  372. *this = this_type(source);
  373. return *this;
  374. }
  375. #endif
  376. /// implicit conversion to @c value_type is allowed
  377. operator value_type() const { return val_; }
  378. const value_type& value() const { return val_; } ///< constant accessor to value
  379. ///< can add a quantity of the same type if add_typeof_helper<value_type,value_type>::type is convertible to value_type
  380. this_type& operator+=(const this_type& source) { val_ += source.val_; return *this; }
  381. ///< can subtract a quantity of the same type if subtract_typeof_helper<value_type,value_type>::type is convertible to value_type
  382. this_type& operator-=(const this_type& source) { val_ -= source.val_; return *this; }
  383. ///< can multiply a quantity by a scalar value_type if multiply_typeof_helper<value_type,value_type>::type is convertible to value_type
  384. this_type& operator*=(const value_type& val) { val_ *= val; return *this; }
  385. ///< can divide a quantity by a scalar value_type if divide_typeof_helper<value_type,value_type>::type is convertible to value_type
  386. this_type& operator/=(const value_type& val) { val_ /= val; return *this; }
  387. /// Construct quantity directly from @c value_type.
  388. static this_type from_value(const value_type& val) { return this_type(val); }
  389. private:
  390. value_type val_;
  391. };
  392. #ifdef BOOST_MSVC
  393. // HACK: For some obscure reason msvc 8.0 needs these specializations
  394. template<class System, class T>
  395. class quantity<unit<int, System>, T> {};
  396. template<class T>
  397. class quantity<int, T> {};
  398. #endif
  399. } // namespace units
  400. } // namespace boost
  401. #if BOOST_UNITS_HAS_BOOST_TYPEOF
  402. #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  403. BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::quantity, 2)
  404. #endif
  405. namespace boost {
  406. namespace units {
  407. namespace detail {
  408. /// helper class for quantity_cast
  409. template<class X,class Y> struct quantity_cast_helper;
  410. /// specialization for casting to the value type
  411. template<class Y,class X,class Unit>
  412. struct quantity_cast_helper<Y,quantity<Unit,X> >
  413. {
  414. typedef Y type;
  415. type operator()(quantity<Unit,X>& source) { return const_cast<X&>(source.value()); }
  416. };
  417. /// specialization for casting to the value type
  418. template<class Y,class X,class Unit>
  419. struct quantity_cast_helper<Y,const quantity<Unit,X> >
  420. {
  421. typedef Y type;
  422. type operator()(const quantity<Unit,X>& source) { return source.value(); }
  423. };
  424. } // namespace detail
  425. /// quantity_cast provides mutating access to underlying quantity value_type
  426. template<class X,class Y>
  427. inline
  428. X
  429. quantity_cast(Y& source)
  430. {
  431. detail::quantity_cast_helper<X,Y> qch;
  432. return qch(source);
  433. }
  434. template<class X,class Y>
  435. inline
  436. X
  437. quantity_cast(const Y& source)
  438. {
  439. detail::quantity_cast_helper<X,const Y> qch;
  440. return qch(source);
  441. }
  442. /// swap quantities
  443. template<class Unit,class Y>
  444. inline void swap(quantity<Unit,Y>& lhs, quantity<Unit,Y>& rhs)
  445. {
  446. using std::swap;
  447. swap(quantity_cast<Y&>(lhs),quantity_cast<Y&>(rhs));
  448. }
  449. /// specialize unary plus typeof helper
  450. /// INTERNAL ONLY
  451. template<class Unit,class Y>
  452. struct unary_plus_typeof_helper< quantity<Unit,Y> >
  453. {
  454. typedef typename unary_plus_typeof_helper<Y>::type value_type;
  455. typedef typename unary_plus_typeof_helper<Unit>::type unit_type;
  456. typedef quantity<unit_type,value_type> type;
  457. };
  458. /// specialize unary minus typeof helper
  459. /// INTERNAL ONLY
  460. template<class Unit,class Y>
  461. struct unary_minus_typeof_helper< quantity<Unit,Y> >
  462. {
  463. typedef typename unary_minus_typeof_helper<Y>::type value_type;
  464. typedef typename unary_minus_typeof_helper<Unit>::type unit_type;
  465. typedef quantity<unit_type,value_type> type;
  466. };
  467. /// specialize add typeof helper
  468. /// INTERNAL ONLY
  469. template<class Unit1,
  470. class Unit2,
  471. class X,
  472. class Y>
  473. struct add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
  474. {
  475. typedef typename add_typeof_helper<X,Y>::type value_type;
  476. typedef typename add_typeof_helper<Unit1,Unit2>::type unit_type;
  477. typedef quantity<unit_type,value_type> type;
  478. };
  479. /// for sun CC we need to invoke SFINAE at
  480. /// the top level, otherwise it will silently
  481. /// return int.
  482. template<class Dim1, class System1,
  483. class Dim2, class System2,
  484. class X,
  485. class Y>
  486. struct add_typeof_helper< quantity<unit<Dim1, System1>,X>,quantity<unit<Dim2, System2>,Y> >
  487. {
  488. };
  489. template<class Dim,
  490. class System,
  491. class X,
  492. class Y>
  493. struct add_typeof_helper< quantity<unit<Dim, System>,X>,quantity<unit<Dim, System>,Y> >
  494. {
  495. typedef typename add_typeof_helper<X,Y>::type value_type;
  496. typedef unit<Dim, System> unit_type;
  497. typedef quantity<unit_type,value_type> type;
  498. };
  499. /// specialize subtract typeof helper
  500. /// INTERNAL ONLY
  501. template<class Unit1,
  502. class Unit2,
  503. class X,
  504. class Y>
  505. struct subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
  506. {
  507. typedef typename subtract_typeof_helper<X,Y>::type value_type;
  508. typedef typename subtract_typeof_helper<Unit1,Unit2>::type unit_type;
  509. typedef quantity<unit_type,value_type> type;
  510. };
  511. // Force adding different units to fail on sun.
  512. template<class Dim1, class System1,
  513. class Dim2, class System2,
  514. class X,
  515. class Y>
  516. struct subtract_typeof_helper< quantity<unit<Dim1, System1>,X>,quantity<unit<Dim2, System2>,Y> >
  517. {
  518. };
  519. template<class Dim,
  520. class System,
  521. class X,
  522. class Y>
  523. struct subtract_typeof_helper< quantity<unit<Dim, System>,X>,quantity<unit<Dim, System>,Y> >
  524. {
  525. typedef typename subtract_typeof_helper<X,Y>::type value_type;
  526. typedef unit<Dim, System> unit_type;
  527. typedef quantity<unit_type,value_type> type;
  528. };
  529. /// scalar times unit typeof helper
  530. /// INTERNAL ONLY
  531. template<class System,
  532. class Dim,
  533. class X>
  534. struct multiply_typeof_helper< X,unit<Dim,System> >
  535. {
  536. typedef X value_type;
  537. typedef unit<Dim,System> unit_type;
  538. typedef quantity<unit_type,value_type> type;
  539. };
  540. /// unit times scalar typeof helper
  541. /// INTERNAL ONLY
  542. template<class System,
  543. class Dim,
  544. class X>
  545. struct multiply_typeof_helper< unit<Dim,System>,X >
  546. {
  547. typedef X value_type;
  548. typedef unit<Dim,System> unit_type;
  549. typedef quantity<unit_type,value_type> type;
  550. };
  551. /// scalar times quantity typeof helper
  552. /// INTERNAL ONLY
  553. template<class Unit,
  554. class X,
  555. class Y>
  556. struct multiply_typeof_helper< X,quantity<Unit,Y> >
  557. {
  558. typedef typename multiply_typeof_helper<X,Y>::type value_type;
  559. typedef Unit unit_type;
  560. typedef quantity<unit_type,value_type> type;
  561. };
  562. /// quantity times scalar typeof helper
  563. /// INTERNAL ONLY
  564. template<class Unit,
  565. class X,
  566. class Y>
  567. struct multiply_typeof_helper< quantity<Unit,X>,Y >
  568. {
  569. typedef typename multiply_typeof_helper<X,Y>::type value_type;
  570. typedef Unit unit_type;
  571. typedef quantity<unit_type,value_type> type;
  572. };
  573. /// unit times quantity typeof helper
  574. /// INTERNAL ONLY
  575. template<class Unit,
  576. class System,
  577. class Dim,
  578. class X>
  579. struct multiply_typeof_helper< unit<Dim,System>,quantity<Unit,X> >
  580. {
  581. typedef X value_type;
  582. typedef typename multiply_typeof_helper< unit<Dim,System>,Unit >::type unit_type;
  583. typedef quantity<unit_type,value_type> type;
  584. };
  585. /// quantity times unit typeof helper
  586. /// INTERNAL ONLY
  587. template<class Unit,
  588. class System,
  589. class Dim,
  590. class X>
  591. struct multiply_typeof_helper< quantity<Unit,X>,unit<Dim,System> >
  592. {
  593. typedef X value_type;
  594. typedef typename multiply_typeof_helper< Unit,unit<Dim,System> >::type unit_type;
  595. typedef quantity<unit_type,value_type> type;
  596. };
  597. /// quantity times quantity typeof helper
  598. /// INTERNAL ONLY
  599. template<class Unit1,
  600. class Unit2,
  601. class X,
  602. class Y>
  603. struct multiply_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
  604. {
  605. typedef typename multiply_typeof_helper<X,Y>::type value_type;
  606. typedef typename multiply_typeof_helper<Unit1,Unit2>::type unit_type;
  607. typedef quantity<unit_type,value_type> type;
  608. };
  609. /// scalar divided by unit typeof helper
  610. /// INTERNAL ONLY
  611. template<class System,
  612. class Dim,
  613. class X>
  614. struct divide_typeof_helper< X,unit<Dim,System> >
  615. {
  616. typedef X value_type;
  617. typedef typename power_typeof_helper< unit<Dim,System>,static_rational<-1> >::type unit_type;
  618. typedef quantity<unit_type,value_type> type;
  619. };
  620. /// unit divided by scalar typeof helper
  621. /// INTERNAL ONLY
  622. template<class System,
  623. class Dim,
  624. class X>
  625. struct divide_typeof_helper< unit<Dim,System>,X >
  626. {
  627. typedef typename divide_typeof_helper<X,X>::type value_type;
  628. typedef unit<Dim,System> unit_type;
  629. typedef quantity<unit_type,value_type> type;
  630. };
  631. /// scalar divided by quantity typeof helper
  632. /// INTERNAL ONLY
  633. template<class Unit,
  634. class X,
  635. class Y>
  636. struct divide_typeof_helper< X,quantity<Unit,Y> >
  637. {
  638. typedef typename divide_typeof_helper<X,Y>::type value_type;
  639. typedef typename power_typeof_helper< Unit,static_rational<-1> >::type unit_type;
  640. typedef quantity<unit_type,value_type> type;
  641. };
  642. /// quantity divided by scalar typeof helper
  643. /// INTERNAL ONLY
  644. template<class Unit,
  645. class X,
  646. class Y>
  647. struct divide_typeof_helper< quantity<Unit,X>,Y >
  648. {
  649. typedef typename divide_typeof_helper<X,Y>::type value_type;
  650. typedef Unit unit_type;
  651. typedef quantity<unit_type,value_type> type;
  652. };
  653. /// unit divided by quantity typeof helper
  654. /// INTERNAL ONLY
  655. template<class Unit,
  656. class System,
  657. class Dim,
  658. class X>
  659. struct divide_typeof_helper< unit<Dim,System>,quantity<Unit,X> >
  660. {
  661. typedef typename divide_typeof_helper<X,X>::type value_type;
  662. typedef typename divide_typeof_helper< unit<Dim,System>,Unit >::type unit_type;
  663. typedef quantity<unit_type,value_type> type;
  664. };
  665. /// quantity divided by unit typeof helper
  666. /// INTERNAL ONLY
  667. template<class Unit,
  668. class System,
  669. class Dim,
  670. class X>
  671. struct divide_typeof_helper< quantity<Unit,X>,unit<Dim,System> >
  672. {
  673. typedef X value_type;
  674. typedef typename divide_typeof_helper< Unit,unit<Dim,System> >::type unit_type;
  675. typedef quantity<unit_type,value_type> type;
  676. };
  677. /// quantity divided by quantity typeof helper
  678. /// INTERNAL ONLY
  679. template<class Unit1,
  680. class Unit2,
  681. class X,
  682. class Y>
  683. struct divide_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
  684. {
  685. typedef typename divide_typeof_helper<X,Y>::type value_type;
  686. typedef typename divide_typeof_helper<Unit1,Unit2>::type unit_type;
  687. typedef quantity<unit_type,value_type> type;
  688. };
  689. /// specialize power typeof helper
  690. /// INTERNAL ONLY
  691. template<class Unit,long N,long D,class Y>
  692. struct power_typeof_helper< quantity<Unit,Y>,static_rational<N,D> >
  693. {
  694. typedef typename power_typeof_helper<Y,static_rational<N,D> >::type value_type;
  695. typedef typename power_typeof_helper<Unit,static_rational<N,D> >::type unit_type;
  696. typedef quantity<unit_type,value_type> type;
  697. static type value(const quantity<Unit,Y>& x)
  698. {
  699. return type::from_value(power_typeof_helper<Y,static_rational<N,D> >::value(x.value()));
  700. }
  701. };
  702. /// specialize root typeof helper
  703. /// INTERNAL ONLY
  704. template<class Unit,long N,long D,class Y>
  705. struct root_typeof_helper< quantity<Unit,Y>,static_rational<N,D> >
  706. {
  707. typedef typename root_typeof_helper<Y,static_rational<N,D> >::type value_type;
  708. typedef typename root_typeof_helper<Unit,static_rational<N,D> >::type unit_type;
  709. typedef quantity<unit_type,value_type> type;
  710. static type value(const quantity<Unit,Y>& x)
  711. {
  712. return type::from_value(root_typeof_helper<Y,static_rational<N,D> >::value(x.value()));
  713. }
  714. };
  715. /// runtime unit times scalar
  716. /// INTERNAL ONLY
  717. template<class System,
  718. class Dim,
  719. class Y>
  720. inline
  721. typename multiply_typeof_helper< unit<Dim,System>,Y >::type
  722. operator*(const unit<Dim,System>&,const Y& rhs)
  723. {
  724. typedef typename multiply_typeof_helper< unit<Dim,System>,Y >::type type;
  725. return type::from_value(rhs);
  726. }
  727. /// runtime unit divided by scalar
  728. template<class System,
  729. class Dim,
  730. class Y>
  731. inline
  732. typename divide_typeof_helper< unit<Dim,System>,Y >::type
  733. operator/(const unit<Dim,System>&,const Y& rhs)
  734. {
  735. typedef typename divide_typeof_helper<unit<Dim,System>,Y>::type type;
  736. return type::from_value(Y(1)/rhs);
  737. }
  738. /// runtime scalar times unit
  739. template<class System,
  740. class Dim,
  741. class Y>
  742. inline
  743. typename multiply_typeof_helper< Y,unit<Dim,System> >::type
  744. operator*(const Y& lhs,const unit<Dim,System>&)
  745. {
  746. typedef typename multiply_typeof_helper< Y,unit<Dim,System> >::type type;
  747. return type::from_value(lhs);
  748. }
  749. /// runtime scalar divided by unit
  750. template<class System,
  751. class Dim,
  752. class Y>
  753. inline
  754. typename divide_typeof_helper< Y,unit<Dim,System> >::type
  755. operator/(const Y& lhs,const unit<Dim,System>&)
  756. {
  757. typedef typename divide_typeof_helper< Y,unit<Dim,System> >::type type;
  758. return type::from_value(lhs);
  759. }
  760. ///// runtime quantity times scalar
  761. //template<class Unit,
  762. // class X,
  763. // class Y>
  764. //inline
  765. //typename multiply_typeof_helper< quantity<Unit,X>,Y >::type
  766. //operator*(const quantity<Unit,X>& lhs,const Y& rhs)
  767. //{
  768. // typedef typename multiply_typeof_helper< quantity<Unit,X>,Y >::type type;
  769. //
  770. // return type::from_value(lhs.value()*rhs);
  771. //}
  772. //
  773. ///// runtime scalar times quantity
  774. //template<class Unit,
  775. // class X,
  776. // class Y>
  777. //inline
  778. //typename multiply_typeof_helper< X,quantity<Unit,Y> >::type
  779. //operator*(const X& lhs,const quantity<Unit,Y>& rhs)
  780. //{
  781. // typedef typename multiply_typeof_helper< X,quantity<Unit,Y> >::type type;
  782. //
  783. // return type::from_value(lhs*rhs.value());
  784. //}
  785. /// runtime quantity times scalar
  786. template<class Unit,
  787. class X>
  788. inline
  789. typename multiply_typeof_helper< quantity<Unit,X>,X >::type
  790. operator*(const quantity<Unit,X>& lhs,const X& rhs)
  791. {
  792. typedef typename multiply_typeof_helper< quantity<Unit,X>,X >::type type;
  793. return type::from_value(lhs.value()*rhs);
  794. }
  795. /// runtime scalar times quantity
  796. template<class Unit,
  797. class X>
  798. inline
  799. typename multiply_typeof_helper< X,quantity<Unit,X> >::type
  800. operator*(const X& lhs,const quantity<Unit,X>& rhs)
  801. {
  802. typedef typename multiply_typeof_helper< X,quantity<Unit,X> >::type type;
  803. return type::from_value(lhs*rhs.value());
  804. }
  805. ///// runtime quantity divided by scalar
  806. //template<class Unit,
  807. // class X,
  808. // class Y>
  809. //inline
  810. //typename divide_typeof_helper< quantity<Unit,X>,Y >::type
  811. //operator/(const quantity<Unit,X>& lhs,const Y& rhs)
  812. //{
  813. // typedef typename divide_typeof_helper< quantity<Unit,X>,Y >::type type;
  814. //
  815. // return type::from_value(lhs.value()/rhs);
  816. //}
  817. //
  818. ///// runtime scalar divided by quantity
  819. //template<class Unit,
  820. // class X,
  821. // class Y>
  822. //inline
  823. //typename divide_typeof_helper< X,quantity<Unit,Y> >::type
  824. //operator/(const X& lhs,const quantity<Unit,Y>& rhs)
  825. //{
  826. // typedef typename divide_typeof_helper< X,quantity<Unit,Y> >::type type;
  827. //
  828. // return type::from_value(lhs/rhs.value());
  829. //}
  830. /// runtime quantity divided by scalar
  831. template<class Unit,
  832. class X>
  833. inline
  834. typename divide_typeof_helper< quantity<Unit,X>,X >::type
  835. operator/(const quantity<Unit,X>& lhs,const X& rhs)
  836. {
  837. typedef typename divide_typeof_helper< quantity<Unit,X>,X >::type type;
  838. return type::from_value(lhs.value()/rhs);
  839. }
  840. /// runtime scalar divided by quantity
  841. template<class Unit,
  842. class X>
  843. inline
  844. typename divide_typeof_helper< X,quantity<Unit,X> >::type
  845. operator/(const X& lhs,const quantity<Unit,X>& rhs)
  846. {
  847. typedef typename divide_typeof_helper< X,quantity<Unit,X> >::type type;
  848. return type::from_value(lhs/rhs.value());
  849. }
  850. /// runtime unit times quantity
  851. template<class System1,
  852. class Dim1,
  853. class Unit2,
  854. class Y>
  855. inline
  856. typename multiply_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type
  857. operator*(const unit<Dim1,System1>&,const quantity<Unit2,Y>& rhs)
  858. {
  859. typedef typename multiply_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type type;
  860. return type::from_value(rhs.value());
  861. }
  862. /// runtime unit divided by quantity
  863. template<class System1,
  864. class Dim1,
  865. class Unit2,
  866. class Y>
  867. inline
  868. typename divide_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type
  869. operator/(const unit<Dim1,System1>&,const quantity<Unit2,Y>& rhs)
  870. {
  871. typedef typename divide_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type type;
  872. return type::from_value(Y(1)/rhs.value());
  873. }
  874. /// runtime quantity times unit
  875. template<class Unit1,
  876. class System2,
  877. class Dim2,
  878. class Y>
  879. inline
  880. typename multiply_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type
  881. operator*(const quantity<Unit1,Y>& lhs,const unit<Dim2,System2>&)
  882. {
  883. typedef typename multiply_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type type;
  884. return type::from_value(lhs.value());
  885. }
  886. /// runtime quantity divided by unit
  887. template<class Unit1,
  888. class System2,
  889. class Dim2,
  890. class Y>
  891. inline
  892. typename divide_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type
  893. operator/(const quantity<Unit1,Y>& lhs,const unit<Dim2,System2>&)
  894. {
  895. typedef typename divide_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type type;
  896. return type::from_value(lhs.value());
  897. }
  898. /// runtime unary plus quantity
  899. template<class Unit,class Y>
  900. typename unary_plus_typeof_helper< quantity<Unit,Y> >::type
  901. operator+(const quantity<Unit,Y>& val)
  902. {
  903. typedef typename unary_plus_typeof_helper< quantity<Unit,Y> >::type type;
  904. return type::from_value(+val.value());
  905. }
  906. /// runtime unary minus quantity
  907. template<class Unit,class Y>
  908. typename unary_minus_typeof_helper< quantity<Unit,Y> >::type
  909. operator-(const quantity<Unit,Y>& val)
  910. {
  911. typedef typename unary_minus_typeof_helper< quantity<Unit,Y> >::type type;
  912. return type::from_value(-val.value());
  913. }
  914. /// runtime quantity plus quantity
  915. template<class Unit1,
  916. class Unit2,
  917. class X,
  918. class Y>
  919. inline
  920. typename add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
  921. operator+(const quantity<Unit1,X>& lhs,
  922. const quantity<Unit2,Y>& rhs)
  923. {
  924. typedef typename add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type type;
  925. return type::from_value(lhs.value()+rhs.value());
  926. }
  927. /// runtime quantity minus quantity
  928. template<class Unit1,
  929. class Unit2,
  930. class X,
  931. class Y>
  932. inline
  933. typename subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
  934. operator-(const quantity<Unit1,X>& lhs,
  935. const quantity<Unit2,Y>& rhs)
  936. {
  937. typedef typename subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type type;
  938. return type::from_value(lhs.value()-rhs.value());
  939. }
  940. /// runtime quantity times quantity
  941. template<class Unit1,
  942. class Unit2,
  943. class X,
  944. class Y>
  945. inline
  946. typename multiply_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
  947. operator*(const quantity<Unit1,X>& lhs,
  948. const quantity<Unit2,Y>& rhs)
  949. {
  950. typedef typename multiply_typeof_helper< quantity<Unit1,X>,
  951. quantity<Unit2,Y> >::type type;
  952. return type::from_value(lhs.value()*rhs.value());
  953. }
  954. /// runtime quantity divided by quantity
  955. template<class Unit1,
  956. class Unit2,
  957. class X,
  958. class Y>
  959. inline
  960. typename divide_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
  961. operator/(const quantity<Unit1,X>& lhs,
  962. const quantity<Unit2,Y>& rhs)
  963. {
  964. typedef typename divide_typeof_helper< quantity<Unit1,X>,
  965. quantity<Unit2,Y> >::type type;
  966. return type::from_value(lhs.value()/rhs.value());
  967. }
  968. /// runtime operator==
  969. template<class Unit,
  970. class X,
  971. class Y>
  972. inline
  973. bool
  974. operator==(const quantity<Unit,X>& val1,
  975. const quantity<Unit,Y>& val2)
  976. {
  977. return val1.value() == val2.value();
  978. }
  979. /// runtime operator!=
  980. template<class Unit,
  981. class X,
  982. class Y>
  983. inline
  984. bool
  985. operator!=(const quantity<Unit,X>& val1,
  986. const quantity<Unit,Y>& val2)
  987. {
  988. return val1.value() != val2.value();
  989. }
  990. /// runtime operator<
  991. template<class Unit,
  992. class X,
  993. class Y>
  994. inline
  995. bool
  996. operator<(const quantity<Unit,X>& val1,
  997. const quantity<Unit,Y>& val2)
  998. {
  999. return val1.value() < val2.value();
  1000. }
  1001. /// runtime operator<=
  1002. template<class Unit,
  1003. class X,
  1004. class Y>
  1005. inline
  1006. bool
  1007. operator<=(const quantity<Unit,X>& val1,
  1008. const quantity<Unit,Y>& val2)
  1009. {
  1010. return val1.value() <= val2.value();
  1011. }
  1012. /// runtime operator>
  1013. template<class Unit,
  1014. class X,
  1015. class Y>
  1016. inline
  1017. bool
  1018. operator>(const quantity<Unit,X>& val1,
  1019. const quantity<Unit,Y>& val2)
  1020. {
  1021. return val1.value() > val2.value();
  1022. }
  1023. /// runtime operator>=
  1024. template<class Unit,
  1025. class X,
  1026. class Y>
  1027. inline
  1028. bool
  1029. operator>=(const quantity<Unit,X>& val1,
  1030. const quantity<Unit,Y>& val2)
  1031. {
  1032. return val1.value() >= val2.value();
  1033. }
  1034. } // namespace units
  1035. } // namespace boost
  1036. #endif // BOOST_UNITS_QUANTITY_HPP