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 BOOST_CONSTEXPR unit() { }
46 BOOST_CONSTEXPR unit(const this_type&) { }
47 //~unit() { }
48
49 BOOST_CXX14_CONSTEXPR 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 BOOST_CONSTEXPR 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 BOOST_CONSTEXPR type value(const unit<Dim,System>&)
321 {
322 return type();
323 }
324};
325
326/// unit runtime unary plus
327template<class Dim,class System>
328BOOST_CONSTEXPR
329typename unary_plus_typeof_helper< unit<Dim,System> >::type
330operator+(const unit<Dim,System>&)
331{
332 typedef typename unary_plus_typeof_helper< unit<Dim,System> >::type type;
333
334 return type();
335}
336
337/// unit runtime unary minus
338template<class Dim,class System>
339BOOST_CONSTEXPR
340typename unary_minus_typeof_helper< unit<Dim,System> >::type
341operator-(const unit<Dim,System>&)
342{
343 typedef typename unary_minus_typeof_helper< unit<Dim,System> >::type type;
344
345 return type();
346}
347
348/// runtime add two units
349template<class Dim1,
350 class Dim2,
351 class System1,
352 class System2>
353BOOST_CONSTEXPR
354typename add_typeof_helper< unit<Dim1,System1>,
355 unit<Dim2,System2> >::type
356operator+(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
357{
358 BOOST_STATIC_ASSERT((boost::is_same<System1,System2>::value == true));
359
360 typedef System1 system_type;
361 typedef typename add_typeof_helper< unit<Dim1,system_type>,
362 unit<Dim2,system_type> >::type type;
363
364 return type();
365}
366
367/// runtime subtract two units
368template<class Dim1,
369 class Dim2,
370 class System1,
371 class System2>
372BOOST_CONSTEXPR
373typename subtract_typeof_helper< unit<Dim1,System1>,
374 unit<Dim2,System2> >::type
375operator-(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
376{
377 BOOST_STATIC_ASSERT((boost::is_same<System1,System2>::value == true));
378
379 typedef System1 system_type;
380 typedef typename subtract_typeof_helper< unit<Dim1,system_type>,
381 unit<Dim2,system_type> >::type type;
382
383 return type();
384}
385
386/// runtime multiply two units
387template<class Dim1,
388 class Dim2,
389 class System1,
390 class System2>
391BOOST_CONSTEXPR
392typename multiply_typeof_helper< unit<Dim1,System1>,
393 unit<Dim2,System2> >::type
394operator*(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
395{
396 typedef typename multiply_typeof_helper< unit<Dim1,System1>,
397 unit<Dim2,System2> >::type type;
398
399 return type();
400}
401
402/// runtime divide two units
403template<class Dim1,
404 class Dim2,
405 class System1,
406 class System2>
407BOOST_CONSTEXPR
408typename divide_typeof_helper< unit<Dim1,System1>,
409 unit<Dim2,System2> >::type
410operator/(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
411{
412 typedef typename divide_typeof_helper< unit<Dim1,System1>,
413 unit<Dim2,System2> >::type type;
414
415 return type();
416}
417
418/// unit runtime @c operator==
419template<class Dim1,
420 class Dim2,
421 class System1,
422 class System2>
423inline
424BOOST_CONSTEXPR
425bool
426operator==(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
427{
428 return boost::is_same<typename reduce_unit<unit<Dim1,System1> >::type, typename reduce_unit<unit<Dim2,System2> >::type>::value;
429}
430
431/// unit runtime @c operator!=
432template<class Dim1,
433 class Dim2,
434 class System1,
435 class System2>
436inline
437BOOST_CONSTEXPR
438bool
439operator!=(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
440{
441 return !boost::is_same<typename reduce_unit<unit<Dim1,System1> >::type, typename reduce_unit<unit<Dim2,System2> >::type>::value;
442}
443
444} // namespace units
445
446} // namespace boost
447
448#endif // BOOST_UNITS_UNIT_HPP
449

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