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
29namespace boost {
30
31namespace units {
32
33/// class representing a model-dependent unit with no associated value
34
35/// (e.g. meters, Kelvin, feet, etc...)
36template<class Dim,class System, class Enable>
37class 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
75BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::unit, 2)
76
77#endif
78
79namespace boost {
80
81namespace units {
82
83/// Returns a unique type for every unit.
84template<class Dim, class System>
85struct 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
97template<class S1,class S2>
98struct 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
104template<class Dim,class System>
105struct 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
112template<class Dim,class System>
113struct unary_minus_typeof_helper< unit<Dim,System> >
114{
115 typedef unit<Dim,System> type;
116};
117
118/// unit add typeof helper
119/// INTERNAL ONLY
120template<class Dim,
121 class System>
122struct 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
129template<class Dim,
130 class System>
131struct 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
138template<class Dim1,
139 class Dim2,
140 class System>
141struct 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
149template<class Dim1,
150 class Dim2,
151 class System1,
152 class System2>
153struct 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
167template<class Dim1,
168 class Dim2,
169 class System1,
170 class System2>
171struct 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
185template<class Dim1,
186 class Dim2,
187 class System1,
188 class System2>
189struct 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
203template<class Dim1,
204 class Dim2,
205 class System1,
206 class System2>
207struct 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
221template<class Dim1,
222 class Dim2,
223 class System>
224struct 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
232template<class Dim1,
233 class Dim2,
234 class System1,
235 class System2>
236struct 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
250template<class Dim1,
251 class Dim2,
252 class System1,
253 class System2>
254struct 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
268template<class Dim1,
269 class Dim2,
270 class System1,
271 class System2>
272struct 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
286template<class Dim1,
287 class Dim2,
288 class System1,
289 class System2>
290struct 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
303template<class Dim,class System,long N,long D>
304struct 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
315template<class Dim,class System,long N,long D>
316struct 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
327template<class Dim,class System>
328typename unary_plus_typeof_helper< unit<Dim,System> >::type
329operator+(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
337template<class Dim,class System>
338typename unary_minus_typeof_helper< unit<Dim,System> >::type
339operator-(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
347template<class Dim1,
348 class Dim2,
349 class System1,
350 class System2>
351typename add_typeof_helper< unit<Dim1,System1>,
352 unit<Dim2,System2> >::type
353operator+(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
365template<class Dim1,
366 class Dim2,
367 class System1,
368 class System2>
369typename subtract_typeof_helper< unit<Dim1,System1>,
370 unit<Dim2,System2> >::type
371operator-(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
383template<class Dim1,
384 class Dim2,
385 class System1,
386 class System2>
387typename multiply_typeof_helper< unit<Dim1,System1>,
388 unit<Dim2,System2> >::type
389operator*(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
398template<class Dim1,
399 class Dim2,
400 class System1,
401 class System2>
402typename divide_typeof_helper< unit<Dim1,System1>,
403 unit<Dim2,System2> >::type
404operator/(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==
413template<class Dim1,
414 class Dim2,
415 class System1,
416 class System2>
417inline
418bool
419operator==(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!=
425template<class Dim1,
426 class Dim2,
427 class System1,
428 class System2>
429inline
430bool
431operator!=(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

source code of boost/boost/units/unit.hpp