unit.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  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) 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_UNIT_HPP
  11. #define BOOST_UNITS_UNIT_HPP
  12. #include <boost/static_assert.hpp>
  13. #include <boost/mpl/bool.hpp>
  14. #include <boost/mpl/assert.hpp>
  15. #include <boost/type_traits/is_same.hpp>
  16. #include <boost/units/config.hpp>
  17. #include <boost/units/dimension.hpp>
  18. #include <boost/units/operators.hpp>
  19. #include <boost/units/units_fwd.hpp>
  20. #include <boost/units/homogeneous_system.hpp>
  21. #include <boost/units/heterogeneous_system.hpp>
  22. #include <boost/units/is_dimension_list.hpp>
  23. #include <boost/units/reduce_unit.hpp>
  24. #include <boost/units/static_rational.hpp>
  25. namespace boost {
  26. namespace units {
  27. /// class representing a model-dependent unit with no associated value
  28. /// (e.g. meters, Kelvin, feet, etc...)
  29. template<class Dim,class System, class Enable>
  30. class unit
  31. {
  32. public:
  33. typedef unit<Dim, System> unit_type;
  34. typedef unit<Dim,System> this_type;
  35. typedef Dim dimension_type;
  36. typedef System system_type;
  37. BOOST_CONSTEXPR unit() { }
  38. BOOST_CONSTEXPR unit(const this_type&) { }
  39. //~unit() { }
  40. BOOST_CXX14_CONSTEXPR this_type& operator=(const this_type&) { return *this; }
  41. // sun will ignore errors resulting from templates
  42. // instantiated in the return type of a function.
  43. // Make sure that we get an error anyway by putting.
  44. // the check in the destructor.
  45. #ifdef __SUNPRO_CC
  46. ~unit() {
  47. BOOST_MPL_ASSERT((detail::check_system<System, Dim>));
  48. BOOST_MPL_ASSERT((is_dimension_list<Dim>));
  49. }
  50. #else
  51. private:
  52. BOOST_MPL_ASSERT((detail::check_system<System, Dim>));
  53. BOOST_MPL_ASSERT((is_dimension_list<Dim>));
  54. #endif
  55. };
  56. }
  57. }
  58. #if BOOST_UNITS_HAS_BOOST_TYPEOF
  59. #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  60. BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::unit, 2)
  61. #endif
  62. namespace boost {
  63. namespace units {
  64. /// Returns a unique type for every unit.
  65. template<class Dim, class System>
  66. struct reduce_unit<unit<Dim, System> >
  67. {
  68. typedef unit<
  69. Dim,
  70. typename detail::make_heterogeneous_system<
  71. Dim,
  72. System
  73. >::type
  74. > type;
  75. };
  76. /// INTERNAL ONLY
  77. template<class S1,class S2>
  78. struct is_implicitly_convertible :
  79. boost::is_same<typename reduce_unit<S1>::type, typename reduce_unit<S2>::type>
  80. { };
  81. /// unit unary plus typeof helper
  82. /// INTERNAL ONLY
  83. template<class Dim,class System>
  84. struct unary_plus_typeof_helper< unit<Dim,System> >
  85. {
  86. typedef unit<Dim,System> type;
  87. };
  88. /// unit unary minus typeof helper
  89. /// INTERNAL ONLY
  90. template<class Dim,class System>
  91. struct unary_minus_typeof_helper< unit<Dim,System> >
  92. {
  93. typedef unit<Dim,System> type;
  94. };
  95. /// unit add typeof helper
  96. /// INTERNAL ONLY
  97. template<class Dim,
  98. class System>
  99. struct add_typeof_helper< unit<Dim,System>,unit<Dim,System> >
  100. {
  101. typedef unit<Dim,System> type;
  102. };
  103. /// unit subtract typeof helper
  104. /// INTERNAL ONLY
  105. template<class Dim,
  106. class System>
  107. struct subtract_typeof_helper< unit<Dim,System>,unit<Dim,System> >
  108. {
  109. typedef unit<Dim,System> type;
  110. };
  111. /// unit multiply typeof helper for two identical homogeneous systems
  112. /// INTERNAL ONLY
  113. template<class Dim1,
  114. class Dim2,
  115. class System>
  116. struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System> >,
  117. unit<Dim2,homogeneous_system<System> > >
  118. {
  119. typedef unit<typename mpl::times<Dim1,Dim2>::type,homogeneous_system<System> > type;
  120. };
  121. /// unit multiply typeof helper for two different homogeneous systems
  122. /// INTERNAL ONLY
  123. template<class Dim1,
  124. class Dim2,
  125. class System1,
  126. class System2>
  127. struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
  128. unit<Dim2,homogeneous_system<System2> > >
  129. {
  130. typedef unit<
  131. typename mpl::times<Dim1,Dim2>::type,
  132. typename detail::multiply_systems<
  133. typename detail::make_heterogeneous_system<Dim1, System1>::type,
  134. typename detail::make_heterogeneous_system<Dim2, System2>::type
  135. >::type
  136. > type;
  137. };
  138. /// unit multiply typeof helper for a heterogeneous and a homogeneous system
  139. /// INTERNAL ONLY
  140. template<class Dim1,
  141. class Dim2,
  142. class System1,
  143. class System2>
  144. struct multiply_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
  145. unit<Dim2,homogeneous_system<System2> > >
  146. {
  147. typedef unit<
  148. typename mpl::times<Dim1,Dim2>::type,
  149. typename detail::multiply_systems<
  150. heterogeneous_system<System1>,
  151. typename detail::make_heterogeneous_system<Dim2, System2>::type
  152. >::type
  153. > type;
  154. };
  155. /// unit multiply typeof helper for a homogeneous and a heterogeneous system
  156. /// INTERNAL ONLY
  157. template<class Dim1,
  158. class Dim2,
  159. class System1,
  160. class System2>
  161. struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
  162. unit<Dim2,heterogeneous_system<System2> > >
  163. {
  164. typedef unit<
  165. typename mpl::times<Dim1,Dim2>::type,
  166. typename detail::multiply_systems<
  167. typename detail::make_heterogeneous_system<Dim1, System1>::type,
  168. heterogeneous_system<System2>
  169. >::type
  170. > type;
  171. };
  172. /// unit multiply typeof helper for two heterogeneous systems
  173. /// INTERNAL ONLY
  174. template<class Dim1,
  175. class Dim2,
  176. class System1,
  177. class System2>
  178. struct multiply_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
  179. unit<Dim2,heterogeneous_system<System2> > >
  180. {
  181. typedef unit<
  182. typename mpl::times<Dim1,Dim2>::type,
  183. typename detail::multiply_systems<
  184. heterogeneous_system<System1>,
  185. heterogeneous_system<System2>
  186. >::type
  187. > type;
  188. };
  189. /// unit divide typeof helper for two identical homogeneous systems
  190. /// INTERNAL ONLY
  191. template<class Dim1,
  192. class Dim2,
  193. class System>
  194. struct divide_typeof_helper< unit<Dim1,homogeneous_system<System> >,
  195. unit<Dim2,homogeneous_system<System> > >
  196. {
  197. typedef unit<typename mpl::divides<Dim1,Dim2>::type,homogeneous_system<System> > type;
  198. };
  199. /// unit divide typeof helper for two different homogeneous systems
  200. /// INTERNAL ONLY
  201. template<class Dim1,
  202. class Dim2,
  203. class System1,
  204. class System2>
  205. struct divide_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
  206. unit<Dim2,homogeneous_system<System2> > >
  207. {
  208. typedef unit<
  209. typename mpl::divides<Dim1,Dim2>::type,
  210. typename detail::divide_systems<
  211. typename detail::make_heterogeneous_system<Dim1, System1>::type,
  212. typename detail::make_heterogeneous_system<Dim2, System2>::type
  213. >::type
  214. > type;
  215. };
  216. /// unit divide typeof helper for a heterogeneous and a homogeneous system
  217. /// INTERNAL ONLY
  218. template<class Dim1,
  219. class Dim2,
  220. class System1,
  221. class System2>
  222. struct divide_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
  223. unit<Dim2,homogeneous_system<System2> > >
  224. {
  225. typedef unit<
  226. typename mpl::divides<Dim1,Dim2>::type,
  227. typename detail::divide_systems<
  228. heterogeneous_system<System1>,
  229. typename detail::make_heterogeneous_system<Dim2, System2>::type
  230. >::type
  231. > type;
  232. };
  233. /// unit divide typeof helper for a homogeneous and a heterogeneous system
  234. /// INTERNAL ONLY
  235. template<class Dim1,
  236. class Dim2,
  237. class System1,
  238. class System2>
  239. struct divide_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
  240. unit<Dim2,heterogeneous_system<System2> > >
  241. {
  242. typedef unit<
  243. typename mpl::divides<Dim1,Dim2>::type,
  244. typename detail::divide_systems<
  245. typename detail::make_heterogeneous_system<Dim1, System1>::type,
  246. heterogeneous_system<System2>
  247. >::type
  248. > type;
  249. };
  250. /// unit divide typeof helper for two heterogeneous systems
  251. /// INTERNAL ONLY
  252. template<class Dim1,
  253. class Dim2,
  254. class System1,
  255. class System2>
  256. struct divide_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
  257. unit<Dim2,heterogeneous_system<System2> > >
  258. {
  259. typedef unit<
  260. typename mpl::divides<Dim1,Dim2>::type,
  261. typename detail::divide_systems<
  262. heterogeneous_system<System1>,
  263. heterogeneous_system<System2>
  264. >::type
  265. > type;
  266. };
  267. /// raise unit to a @c static_rational power
  268. template<class Dim,class System,long N,long D>
  269. struct power_typeof_helper<unit<Dim,System>,static_rational<N,D> >
  270. {
  271. typedef unit<typename static_power<Dim,static_rational<N,D> >::type,typename static_power<System, static_rational<N,D> >::type> type;
  272. static BOOST_CONSTEXPR type value(const unit<Dim,System>&)
  273. {
  274. return type();
  275. }
  276. };
  277. /// take the @c static_rational root of a unit
  278. template<class Dim,class System,long N,long D>
  279. struct root_typeof_helper<unit<Dim,System>,static_rational<N,D> >
  280. {
  281. typedef unit<typename static_root<Dim,static_rational<N,D> >::type,typename static_root<System, static_rational<N,D> >::type> type;
  282. static BOOST_CONSTEXPR type value(const unit<Dim,System>&)
  283. {
  284. return type();
  285. }
  286. };
  287. /// unit runtime unary plus
  288. template<class Dim,class System>
  289. BOOST_CONSTEXPR
  290. typename unary_plus_typeof_helper< unit<Dim,System> >::type
  291. operator+(const unit<Dim,System>&)
  292. {
  293. typedef typename unary_plus_typeof_helper< unit<Dim,System> >::type type;
  294. return type();
  295. }
  296. /// unit runtime unary minus
  297. template<class Dim,class System>
  298. BOOST_CONSTEXPR
  299. typename unary_minus_typeof_helper< unit<Dim,System> >::type
  300. operator-(const unit<Dim,System>&)
  301. {
  302. typedef typename unary_minus_typeof_helper< unit<Dim,System> >::type type;
  303. return type();
  304. }
  305. /// runtime add two units
  306. template<class Dim1,
  307. class Dim2,
  308. class System1,
  309. class System2>
  310. BOOST_CONSTEXPR
  311. typename add_typeof_helper< unit<Dim1,System1>,
  312. unit<Dim2,System2> >::type
  313. operator+(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
  314. {
  315. BOOST_STATIC_ASSERT((boost::is_same<System1,System2>::value == true));
  316. typedef System1 system_type;
  317. typedef typename add_typeof_helper< unit<Dim1,system_type>,
  318. unit<Dim2,system_type> >::type type;
  319. return type();
  320. }
  321. /// runtime subtract two units
  322. template<class Dim1,
  323. class Dim2,
  324. class System1,
  325. class System2>
  326. BOOST_CONSTEXPR
  327. typename subtract_typeof_helper< unit<Dim1,System1>,
  328. unit<Dim2,System2> >::type
  329. operator-(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
  330. {
  331. BOOST_STATIC_ASSERT((boost::is_same<System1,System2>::value == true));
  332. typedef System1 system_type;
  333. typedef typename subtract_typeof_helper< unit<Dim1,system_type>,
  334. unit<Dim2,system_type> >::type type;
  335. return type();
  336. }
  337. /// runtime multiply two units
  338. template<class Dim1,
  339. class Dim2,
  340. class System1,
  341. class System2>
  342. BOOST_CONSTEXPR
  343. typename multiply_typeof_helper< unit<Dim1,System1>,
  344. unit<Dim2,System2> >::type
  345. operator*(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
  346. {
  347. typedef typename multiply_typeof_helper< unit<Dim1,System1>,
  348. unit<Dim2,System2> >::type type;
  349. return type();
  350. }
  351. /// runtime divide two units
  352. template<class Dim1,
  353. class Dim2,
  354. class System1,
  355. class System2>
  356. BOOST_CONSTEXPR
  357. typename divide_typeof_helper< unit<Dim1,System1>,
  358. unit<Dim2,System2> >::type
  359. operator/(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
  360. {
  361. typedef typename divide_typeof_helper< unit<Dim1,System1>,
  362. unit<Dim2,System2> >::type type;
  363. return type();
  364. }
  365. /// unit runtime @c operator==
  366. template<class Dim1,
  367. class Dim2,
  368. class System1,
  369. class System2>
  370. inline
  371. BOOST_CONSTEXPR
  372. bool
  373. operator==(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
  374. {
  375. return boost::is_same<typename reduce_unit<unit<Dim1,System1> >::type, typename reduce_unit<unit<Dim2,System2> >::type>::value;
  376. }
  377. /// unit runtime @c operator!=
  378. template<class Dim1,
  379. class Dim2,
  380. class System1,
  381. class System2>
  382. inline
  383. BOOST_CONSTEXPR
  384. bool
  385. operator!=(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
  386. {
  387. return !boost::is_same<typename reduce_unit<unit<Dim1,System1> >::type, typename reduce_unit<unit<Dim2,System2> >::type>::value;
  388. }
  389. } // namespace units
  390. } // namespace boost
  391. #endif // BOOST_UNITS_UNIT_HPP