]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |