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