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) 2007-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_QUANTITY_HPP
12#define BOOST_UNITS_QUANTITY_HPP
13
14#include <algorithm>
15
16#include <boost/config.hpp>
17#include <boost/static_assert.hpp>
18#include <boost/mpl/bool.hpp>
19#include <boost/mpl/and.hpp>
20#include <boost/mpl/not.hpp>
21#include <boost/mpl/or.hpp>
22#include <boost/mpl/assert.hpp>
23#include <boost/utility/enable_if.hpp>
24#include <boost/type_traits/is_arithmetic.hpp>
25#include <boost/type_traits/is_convertible.hpp>
26#include <boost/type_traits/is_integral.hpp>
27#include <boost/type_traits/is_same.hpp>
28
29#include <boost/units/conversion.hpp>
30#include <boost/units/dimensionless_type.hpp>
31#include <boost/units/homogeneous_system.hpp>
32#include <boost/units/operators.hpp>
33#include <boost/units/static_rational.hpp>
34#include <boost/units/units_fwd.hpp>
35#include <boost/units/detail/dimensionless_unit.hpp>
36
37namespace boost {
38
39namespace units {
40
41namespace detail {
42
43template<class T, class Enable = void>
44struct is_base_unit : mpl::false_ {};
45
46template<class T>
47struct is_base_unit<T, typename T::boost_units_is_base_unit_type> : mpl::true_ {};
48
49template<class Source, class Destination>
50struct is_narrowing_conversion_impl : mpl::bool_<(sizeof(Source) > sizeof(Destination))> {};
51
52template<class Source, class Destination>
53struct is_non_narrowing_conversion :
54 mpl::and_<
55 boost::is_convertible<Source, Destination>,
56 mpl::not_<
57 mpl::and_<
58 boost::is_arithmetic<Source>,
59 boost::is_arithmetic<Destination>,
60 mpl::or_<
61 mpl::and_<
62 is_integral<Destination>,
63 mpl::not_<is_integral<Source> >
64 >,
65 is_narrowing_conversion_impl<Source, Destination>
66 >
67 >
68 >
69 >
70{};
71
72template<>
73struct is_non_narrowing_conversion<long double, double> : mpl::false_ {};
74
75// msvc 7.1 needs extra disambiguation
76template<class T, class U>
77struct disable_if_is_same
78{
79 typedef void type;
80};
81
82template<class T>
83struct disable_if_is_same<T, T> {};
84
85}
86
87/// class declaration
88template<class Unit,class Y>
89class quantity
90{
91 // base units are not the same as units.
92 BOOST_MPL_ASSERT_NOT((detail::is_base_unit<Unit>));
93 enum { force_instantiation_of_unit = sizeof(Unit) };
94 typedef void (quantity::*unspecified_null_pointer_constant_type)(int*******);
95 public:
96 typedef quantity<Unit,Y> this_type;
97
98 typedef Y value_type;
99 typedef Unit unit_type;
100
101 quantity() : val_()
102 {
103 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
104 }
105
106 quantity(unspecified_null_pointer_constant_type) : val_()
107 {
108 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
109 }
110
111 quantity(const this_type& source) : val_(source.val_)
112 {
113 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
114 }
115
116 // Need to make sure that the destructor of
117 // Unit which contains the checking is instantiated,
118 // on sun.
119 #ifdef __SUNPRO_CC
120 ~quantity() {
121 unit_type force_unit_instantiation;
122 }
123 #endif
124
125 //~quantity() { }
126
127 this_type& operator=(const this_type& source)
128 {
129 val_ = source.val_;
130
131 return *this;
132 }
133
134 #ifndef BOOST_NO_SFINAE
135
136 /// implicit conversion between value types is allowed if allowed for value types themselves
137 template<class YY>
138 quantity(const quantity<Unit,YY>& source,
139 typename boost::enable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
140 val_(source.value())
141 {
142 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
143 }
144
145 /// implicit conversion between value types is not allowed if not allowed for value types themselves
146 template<class YY>
147 explicit quantity(const quantity<Unit,YY>& source,
148 typename boost::disable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
149 val_(static_cast<Y>(source.value()))
150 {
151 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
152 }
153
154 #else
155
156 /// implicit conversion between value types is allowed if allowed for value types themselves
157 template<class YY>
158 quantity(const quantity<Unit,YY>& source) :
159 val_(source.value())
160 {
161 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
162 BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
163 }
164
165 #endif
166
167 /// implicit assignment between value types is allowed if allowed for value types themselves
168 template<class YY>
169 this_type& operator=(const quantity<Unit,YY>& source)
170 {
171 BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
172
173 *this = this_type(source);
174
175 return *this;
176 }
177
178 #ifndef BOOST_NO_SFINAE
179
180 /// explicit conversion between different unit systems is allowed if implicit conversion is disallowed
181 template<class Unit2,class YY>
182 explicit
183 quantity(const quantity<Unit2,YY>& source,
184 typename boost::disable_if<
185 mpl::and_<
186 //is_implicitly_convertible should be undefined when the
187 //units are not convertible at all
188 typename is_implicitly_convertible<Unit2,Unit>::type,
189 detail::is_non_narrowing_conversion<YY, Y>
190 >,
191 typename detail::disable_if_is_same<Unit, Unit2>::type
192 >::type* = 0)
193 : val_(conversion_helper<quantity<Unit2,YY>,this_type>::convert(source).value())
194 {
195 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
196 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
197 }
198
199 /// implicit conversion between different unit systems is allowed if each fundamental dimension is implicitly convertible
200 template<class Unit2,class YY>
201 quantity(const quantity<Unit2,YY>& source,
202 typename boost::enable_if<
203 mpl::and_<
204 typename is_implicitly_convertible<Unit2,Unit>::type,
205 detail::is_non_narrowing_conversion<YY, Y>
206 >,
207 typename detail::disable_if_is_same<Unit, Unit2>::type
208 >::type* = 0)
209 : val_(conversion_helper<quantity<Unit2,YY>,this_type>::convert(source).value())
210 {
211 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
212 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
213 }
214
215 #else
216
217 /// without SFINAE we can't distinguish between explicit and implicit conversions so
218 /// the conversion is always explicit
219 template<class Unit2,class YY>
220 explicit quantity(const quantity<Unit2,YY>& source)
221 : val_(conversion_helper<quantity<Unit2,YY>,this_type>::convert(source).value())
222 {
223 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
224 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
225 }
226
227 #endif
228
229 /// implicit assignment between different unit systems is allowed if each fundamental dimension is implicitly convertible
230 template<class Unit2,class YY>
231 this_type& operator=(const quantity<Unit2,YY>& source)
232 {
233
234 BOOST_STATIC_ASSERT((is_implicitly_convertible<Unit2,unit_type>::value == true));
235 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
236
237 *this = this_type(source);
238
239 return *this;
240 }
241
242 const value_type& value() const { return val_; } ///< constant accessor to value
243
244 ///< can add a quantity of the same type if add_typeof_helper<value_type,value_type>::type is convertible to value_type
245 template<class Unit2, class YY>
246 this_type& operator+=(const quantity<Unit2, YY>& source)
247 {
248 BOOST_STATIC_ASSERT((boost::is_same<typename add_typeof_helper<Unit, Unit2>::type, Unit>::value));
249 val_ += source.value();
250 return *this;
251 }
252
253 ///< can subtract a quantity of the same type if subtract_typeof_helper<value_type,value_type>::type is convertible to value_type
254 template<class Unit2, class YY>
255 this_type& operator-=(const quantity<Unit2, YY>& source)
256 {
257 BOOST_STATIC_ASSERT((boost::is_same<typename subtract_typeof_helper<Unit, Unit2>::type, Unit>::value));
258 val_ -= source.value();
259 return *this;
260 }
261
262 template<class Unit2, class YY>
263 this_type& operator*=(const quantity<Unit2, YY>& source)
264 {
265 BOOST_STATIC_ASSERT((boost::is_same<typename multiply_typeof_helper<Unit, Unit2>::type, Unit>::value));
266 val_ *= source.value();
267 return *this;
268 }
269
270 template<class Unit2, class YY>
271 this_type& operator/=(const quantity<Unit2, YY>& source)
272 {
273 BOOST_STATIC_ASSERT((boost::is_same<typename divide_typeof_helper<Unit, Unit2>::type, Unit>::value));
274 val_ /= source.value();
275 return *this;
276 }
277
278 ///< can multiply a quantity by a scalar value_type if multiply_typeof_helper<value_type,value_type>::type is convertible to value_type
279 this_type& operator*=(const value_type& source) { val_ *= source; return *this; }
280 ///< can divide a quantity by a scalar value_type if divide_typeof_helper<value_type,value_type>::type is convertible to value_type
281 this_type& operator/=(const value_type& source) { val_ /= source; return *this; }
282
283 /// Construct quantity directly from @c value_type (potentially dangerous).
284 static this_type from_value(const value_type& val) { return this_type(val, 0); }
285
286 protected:
287 explicit quantity(const value_type& val, int) : val_(val) { }
288
289 private:
290 value_type val_;
291};
292
293/// Specialization for dimensionless quantities. Implicit conversions between
294/// unit systems are allowed because all dimensionless quantities are equivalent.
295/// Implicit construction and assignment from and conversion to @c value_type is
296/// also allowed.
297template<class System,class Y>
298class quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(System),Y>
299{
300 public:
301 typedef quantity<unit<dimensionless_type,System>,Y> this_type;
302
303 typedef Y value_type;
304 typedef System system_type;
305 typedef dimensionless_type dimension_type;
306 typedef unit<dimension_type,system_type> unit_type;
307
308 quantity() : val_()
309 {
310 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
311 }
312
313 /// construction from raw @c value_type is allowed
314 quantity(value_type val) : val_(val)
315 {
316 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
317 }
318
319 quantity(const this_type& source) : val_(source.val_)
320 {
321 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
322 }
323
324 //~quantity() { }
325
326 this_type& operator=(const this_type& source)
327 {
328 val_ = source.val_;
329
330 return *this;
331 }
332
333 #ifndef BOOST_NO_SFINAE
334
335 /// implicit conversion between value types is allowed if allowed for value types themselves
336 template<class YY>
337 quantity(const quantity<unit<dimension_type,system_type>,YY>& source,
338 typename boost::enable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
339 val_(source.value())
340 {
341 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
342 }
343
344 /// implicit conversion between value types is not allowed if not allowed for value types themselves
345 template<class YY>
346 explicit quantity(const quantity<unit<dimension_type,system_type>,YY>& source,
347 typename boost::disable_if<detail::is_non_narrowing_conversion<YY, Y> >::type* = 0) :
348 val_(static_cast<Y>(source.value()))
349 {
350 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
351 }
352
353 #else
354
355 /// implicit conversion between value types is allowed if allowed for value types themselves
356 template<class YY>
357 quantity(const quantity<unit<dimension_type,system_type>,YY>& source) :
358 val_(source.value())
359 {
360 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
361 BOOST_STATIC_ASSERT((boost::is_convertible<YY, Y>::value == true));
362 }
363
364 #endif
365
366 /// implicit assignment between value types is allowed if allowed for value types themselves
367 template<class YY>
368 this_type& operator=(const quantity<unit<dimension_type,system_type>,YY>& source)
369 {
370 BOOST_STATIC_ASSERT((boost::is_convertible<YY,Y>::value == true));
371
372 *this = this_type(source);
373
374 return *this;
375 }
376
377 #if 1
378
379 /// implicit conversion between different unit systems is allowed
380 template<class System2, class Y2>
381 quantity(const quantity<unit<dimensionless_type, System2>,Y2>& source,
382 #ifdef __SUNPRO_CC
383 typename boost::enable_if<
384 boost::mpl::and_<
385 detail::is_non_narrowing_conversion<Y2, Y>,
386 detail::is_dimensionless_system<System2>
387 >
388 >::type* = 0
389 #else
390 typename boost::enable_if<detail::is_non_narrowing_conversion<Y2, Y> >::type* = 0,
391 typename detail::disable_if_is_same<System, System2>::type* = 0,
392 typename boost::enable_if<detail::is_dimensionless_system<System2> >::type* = 0
393 #endif
394 ) :
395 val_(source.value())
396 {
397 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
398 }
399
400 /// implicit conversion between different unit systems is allowed
401 template<class System2, class Y2>
402 explicit quantity(const quantity<unit<dimensionless_type, System2>,Y2>& source,
403 #ifdef __SUNPRO_CC
404 typename boost::enable_if<
405 boost::mpl::and_<
406 boost::mpl::not_<detail::is_non_narrowing_conversion<Y2, Y> >,
407 detail::is_dimensionless_system<System2>
408 >
409 >::type* = 0
410 #else
411 typename boost::disable_if<detail::is_non_narrowing_conversion<Y2, Y> >::type* = 0,
412 typename detail::disable_if_is_same<System, System2>::type* = 0,
413 typename boost::enable_if<detail::is_dimensionless_system<System2> >::type* = 0
414 #endif
415 ) :
416 val_(static_cast<Y>(source.value()))
417 {
418 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
419 }
420
421 #else
422
423 /// implicit conversion between different unit systems is allowed
424 template<class System2, class Y2>
425 quantity(const quantity<unit<dimensionless_type,homogeneous_system<System2> >,Y2>& source) :
426 val_(source.value())
427 {
428 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
429 BOOST_STATIC_ASSERT((boost::is_convertible<Y2, Y>::value == true));
430 }
431
432 #endif
433
434 /// conversion between different unit systems is explicit when
435 /// the units are not equivalent.
436 template<class System2, class Y2>
437 explicit quantity(const quantity<unit<dimensionless_type, System2>,Y2>& source,
438 typename boost::disable_if<detail::is_dimensionless_system<System2> >::type* = 0) :
439 val_(conversion_helper<quantity<unit<dimensionless_type, System2>,Y2>, this_type>::convert(source).value())
440 {
441 BOOST_UNITS_CHECK_LAYOUT_COMPATIBILITY(this_type, Y);
442 }
443
444 #ifndef __SUNPRO_CC
445
446 /// implicit assignment between different unit systems is allowed
447 template<class System2>
448 this_type& operator=(const quantity<BOOST_UNITS_DIMENSIONLESS_UNIT(System2),Y>& source)
449 {
450 *this = this_type(source);
451
452 return *this;
453 }
454
455 #endif
456
457 /// implicit conversion to @c value_type is allowed
458 operator value_type() const { return val_; }
459
460 const value_type& value() const { return val_; } ///< constant accessor to value
461
462 ///< can add a quantity of the same type if add_typeof_helper<value_type,value_type>::type is convertible to value_type
463 this_type& operator+=(const this_type& source) { val_ += source.val_; return *this; }
464
465 ///< can subtract a quantity of the same type if subtract_typeof_helper<value_type,value_type>::type is convertible to value_type
466 this_type& operator-=(const this_type& source) { val_ -= source.val_; return *this; }
467
468 ///< can multiply a quantity by a scalar value_type if multiply_typeof_helper<value_type,value_type>::type is convertible to value_type
469 this_type& operator*=(const value_type& val) { val_ *= val; return *this; }
470
471 ///< can divide a quantity by a scalar value_type if divide_typeof_helper<value_type,value_type>::type is convertible to value_type
472 this_type& operator/=(const value_type& val) { val_ /= val; return *this; }
473
474 /// Construct quantity directly from @c value_type.
475 static this_type from_value(const value_type& val) { return this_type(val); }
476
477 private:
478 value_type val_;
479};
480
481#ifdef BOOST_MSVC
482// HACK: For some obscure reason msvc 8.0 needs these specializations
483template<class System, class T>
484class quantity<unit<int, System>, T> {};
485template<class T>
486class quantity<int, T> {};
487#endif
488
489} // namespace units
490
491} // namespace boost
492
493#if BOOST_UNITS_HAS_BOOST_TYPEOF
494
495#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
496
497BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::quantity, 2)
498
499#endif
500
501namespace boost {
502
503namespace units {
504
505namespace detail {
506
507/// helper class for quantity_cast
508template<class X,class Y> struct quantity_cast_helper;
509
510/// specialization for casting to the value type
511template<class Y,class X,class Unit>
512struct quantity_cast_helper<Y,quantity<Unit,X> >
513{
514 typedef Y type;
515
516 type operator()(quantity<Unit,X>& source) { return const_cast<X&>(source.value()); }
517};
518
519/// specialization for casting to the value type
520template<class Y,class X,class Unit>
521struct quantity_cast_helper<Y,const quantity<Unit,X> >
522{
523 typedef Y type;
524
525 type operator()(const quantity<Unit,X>& source) { return source.value(); }
526};
527
528} // namespace detail
529
530/// quantity_cast provides mutating access to underlying quantity value_type
531template<class X,class Y>
532inline
533X
534quantity_cast(Y& source)
535{
536 detail::quantity_cast_helper<X,Y> qch;
537
538 return qch(source);
539}
540
541template<class X,class Y>
542inline
543X
544quantity_cast(const Y& source)
545{
546 detail::quantity_cast_helper<X,const Y> qch;
547
548 return qch(source);
549}
550
551/// swap quantities
552template<class Unit,class Y>
553inline void swap(quantity<Unit,Y>& lhs, quantity<Unit,Y>& rhs)
554{
555 using std::swap;
556 swap(quantity_cast<Y&>(lhs),quantity_cast<Y&>(rhs));
557}
558
559/// specialize unary plus typeof helper
560/// INTERNAL ONLY
561template<class Unit,class Y>
562struct unary_plus_typeof_helper< quantity<Unit,Y> >
563{
564 typedef typename unary_plus_typeof_helper<Y>::type value_type;
565 typedef typename unary_plus_typeof_helper<Unit>::type unit_type;
566 typedef quantity<unit_type,value_type> type;
567};
568
569/// specialize unary minus typeof helper
570/// INTERNAL ONLY
571template<class Unit,class Y>
572struct unary_minus_typeof_helper< quantity<Unit,Y> >
573{
574 typedef typename unary_minus_typeof_helper<Y>::type value_type;
575 typedef typename unary_minus_typeof_helper<Unit>::type unit_type;
576 typedef quantity<unit_type,value_type> type;
577};
578
579/// specialize add typeof helper
580/// INTERNAL ONLY
581template<class Unit1,
582 class Unit2,
583 class X,
584 class Y>
585struct add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
586{
587 typedef typename add_typeof_helper<X,Y>::type value_type;
588 typedef typename add_typeof_helper<Unit1,Unit2>::type unit_type;
589 typedef quantity<unit_type,value_type> type;
590};
591
592/// for sun CC we need to invoke SFINAE at
593/// the top level, otherwise it will silently
594/// return int.
595template<class Dim1, class System1,
596 class Dim2, class System2,
597 class X,
598 class Y>
599struct add_typeof_helper< quantity<unit<Dim1, System1>,X>,quantity<unit<Dim2, System2>,Y> >
600{
601};
602
603template<class Dim,
604 class System,
605 class X,
606 class Y>
607struct add_typeof_helper< quantity<unit<Dim, System>,X>,quantity<unit<Dim, System>,Y> >
608{
609 typedef typename add_typeof_helper<X,Y>::type value_type;
610 typedef unit<Dim, System> unit_type;
611 typedef quantity<unit_type,value_type> type;
612};
613
614/// specialize subtract typeof helper
615/// INTERNAL ONLY
616template<class Unit1,
617 class Unit2,
618 class X,
619 class Y>
620struct subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
621{
622 typedef typename subtract_typeof_helper<X,Y>::type value_type;
623 typedef typename subtract_typeof_helper<Unit1,Unit2>::type unit_type;
624 typedef quantity<unit_type,value_type> type;
625};
626
627// Force adding different units to fail on sun.
628template<class Dim1, class System1,
629 class Dim2, class System2,
630 class X,
631 class Y>
632struct subtract_typeof_helper< quantity<unit<Dim1, System1>,X>,quantity<unit<Dim2, System2>,Y> >
633{
634};
635
636template<class Dim,
637 class System,
638 class X,
639 class Y>
640struct subtract_typeof_helper< quantity<unit<Dim, System>,X>,quantity<unit<Dim, System>,Y> >
641{
642 typedef typename subtract_typeof_helper<X,Y>::type value_type;
643 typedef unit<Dim, System> unit_type;
644 typedef quantity<unit_type,value_type> type;
645};
646
647/// scalar times unit typeof helper
648/// INTERNAL ONLY
649template<class System,
650 class Dim,
651 class X>
652struct multiply_typeof_helper< X,unit<Dim,System> >
653{
654 typedef X value_type;
655 typedef unit<Dim,System> unit_type;
656 typedef quantity<unit_type,value_type> type;
657};
658
659/// unit times scalar typeof helper
660/// INTERNAL ONLY
661template<class System,
662 class Dim,
663 class X>
664struct multiply_typeof_helper< unit<Dim,System>,X >
665{
666 typedef X value_type;
667 typedef unit<Dim,System> unit_type;
668 typedef quantity<unit_type,value_type> type;
669};
670
671/// scalar times quantity typeof helper
672/// INTERNAL ONLY
673template<class Unit,
674 class X,
675 class Y>
676struct multiply_typeof_helper< X,quantity<Unit,Y> >
677{
678 typedef typename multiply_typeof_helper<X,Y>::type value_type;
679 typedef Unit unit_type;
680 typedef quantity<unit_type,value_type> type;
681};
682
683/// disambiguate
684/// INTERNAL ONLY
685template<class Unit,
686 class Y>
687struct multiply_typeof_helper< one,quantity<Unit,Y> >
688{
689 typedef quantity<Unit,Y> type;
690};
691
692/// quantity times scalar typeof helper
693/// INTERNAL ONLY
694template<class Unit,
695 class X,
696 class Y>
697struct multiply_typeof_helper< quantity<Unit,X>,Y >
698{
699 typedef typename multiply_typeof_helper<X,Y>::type value_type;
700 typedef Unit unit_type;
701 typedef quantity<unit_type,value_type> type;
702};
703
704/// disambiguate
705/// INTERNAL ONLY
706template<class Unit,
707 class X>
708struct multiply_typeof_helper< quantity<Unit,X>,one >
709{
710 typedef quantity<Unit,X> type;
711};
712
713/// unit times quantity typeof helper
714/// INTERNAL ONLY
715template<class Unit,
716 class System,
717 class Dim,
718 class X>
719struct multiply_typeof_helper< unit<Dim,System>,quantity<Unit,X> >
720{
721 typedef X value_type;
722 typedef typename multiply_typeof_helper< unit<Dim,System>,Unit >::type unit_type;
723 typedef quantity<unit_type,value_type> type;
724};
725
726/// quantity times unit typeof helper
727/// INTERNAL ONLY
728template<class Unit,
729 class System,
730 class Dim,
731 class X>
732struct multiply_typeof_helper< quantity<Unit,X>,unit<Dim,System> >
733{
734 typedef X value_type;
735 typedef typename multiply_typeof_helper< Unit,unit<Dim,System> >::type unit_type;
736 typedef quantity<unit_type,value_type> type;
737};
738
739/// quantity times quantity typeof helper
740/// INTERNAL ONLY
741template<class Unit1,
742 class Unit2,
743 class X,
744 class Y>
745struct multiply_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
746{
747 typedef typename multiply_typeof_helper<X,Y>::type value_type;
748 typedef typename multiply_typeof_helper<Unit1,Unit2>::type unit_type;
749 typedef quantity<unit_type,value_type> type;
750};
751
752/// scalar divided by unit typeof helper
753/// INTERNAL ONLY
754template<class System,
755 class Dim,
756 class X>
757struct divide_typeof_helper< X,unit<Dim,System> >
758{
759 typedef X value_type;
760 typedef typename power_typeof_helper< unit<Dim,System>,static_rational<-1> >::type unit_type;
761 typedef quantity<unit_type,value_type> type;
762};
763
764/// unit divided by scalar typeof helper
765/// INTERNAL ONLY
766template<class System,
767 class Dim,
768 class X>
769struct divide_typeof_helper< unit<Dim,System>,X >
770{
771 typedef typename divide_typeof_helper<X,X>::type value_type;
772 typedef unit<Dim,System> unit_type;
773 typedef quantity<unit_type,value_type> type;
774};
775
776/// scalar divided by quantity typeof helper
777/// INTERNAL ONLY
778template<class Unit,
779 class X,
780 class Y>
781struct divide_typeof_helper< X,quantity<Unit,Y> >
782{
783 typedef typename divide_typeof_helper<X,Y>::type value_type;
784 typedef typename power_typeof_helper< Unit,static_rational<-1> >::type unit_type;
785 typedef quantity<unit_type,value_type> type;
786};
787
788/// disambiguate
789/// INTERNAL ONLY
790template<class Unit,
791 class Y>
792struct divide_typeof_helper< one,quantity<Unit,Y> >
793{
794 typedef quantity<Unit,Y> type;
795};
796
797/// quantity divided by scalar typeof helper
798/// INTERNAL ONLY
799template<class Unit,
800 class X,
801 class Y>
802struct divide_typeof_helper< quantity<Unit,X>,Y >
803{
804 typedef typename divide_typeof_helper<X,Y>::type value_type;
805 typedef Unit unit_type;
806 typedef quantity<unit_type,value_type> type;
807};
808
809/// disambiguate
810/// INTERNAL ONLY
811template<class Unit,
812 class X>
813struct divide_typeof_helper< quantity<Unit,X>,one >
814{
815 typedef quantity<Unit,X> type;
816};
817
818/// unit divided by quantity typeof helper
819/// INTERNAL ONLY
820template<class Unit,
821 class System,
822 class Dim,
823 class X>
824struct divide_typeof_helper< unit<Dim,System>,quantity<Unit,X> >
825{
826 typedef typename divide_typeof_helper<X,X>::type value_type;
827 typedef typename divide_typeof_helper< unit<Dim,System>,Unit >::type unit_type;
828 typedef quantity<unit_type,value_type> type;
829};
830
831/// quantity divided by unit typeof helper
832/// INTERNAL ONLY
833template<class Unit,
834 class System,
835 class Dim,
836 class X>
837struct divide_typeof_helper< quantity<Unit,X>,unit<Dim,System> >
838{
839 typedef X value_type;
840 typedef typename divide_typeof_helper< Unit,unit<Dim,System> >::type unit_type;
841 typedef quantity<unit_type,value_type> type;
842};
843
844/// quantity divided by quantity typeof helper
845/// INTERNAL ONLY
846template<class Unit1,
847 class Unit2,
848 class X,
849 class Y>
850struct divide_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >
851{
852 typedef typename divide_typeof_helper<X,Y>::type value_type;
853 typedef typename divide_typeof_helper<Unit1,Unit2>::type unit_type;
854 typedef quantity<unit_type,value_type> type;
855};
856
857/// specialize power typeof helper
858/// INTERNAL ONLY
859template<class Unit,long N,long D,class Y>
860struct power_typeof_helper< quantity<Unit,Y>,static_rational<N,D> >
861{
862 typedef typename power_typeof_helper<Y,static_rational<N,D> >::type value_type;
863 typedef typename power_typeof_helper<Unit,static_rational<N,D> >::type unit_type;
864 typedef quantity<unit_type,value_type> type;
865
866 static type value(const quantity<Unit,Y>& x)
867 {
868 return type::from_value(power_typeof_helper<Y,static_rational<N,D> >::value(x.value()));
869 }
870};
871
872/// specialize root typeof helper
873/// INTERNAL ONLY
874template<class Unit,long N,long D,class Y>
875struct root_typeof_helper< quantity<Unit,Y>,static_rational<N,D> >
876{
877 typedef typename root_typeof_helper<Y,static_rational<N,D> >::type value_type;
878 typedef typename root_typeof_helper<Unit,static_rational<N,D> >::type unit_type;
879 typedef quantity<unit_type,value_type> type;
880
881 static type value(const quantity<Unit,Y>& x)
882 {
883 return type::from_value(root_typeof_helper<Y,static_rational<N,D> >::value(x.value()));
884 }
885};
886
887/// runtime unit times scalar
888/// INTERNAL ONLY
889template<class System,
890 class Dim,
891 class Y>
892inline
893typename multiply_typeof_helper< unit<Dim,System>,Y >::type
894operator*(const unit<Dim,System>&,const Y& rhs)
895{
896 typedef typename multiply_typeof_helper< unit<Dim,System>,Y >::type type;
897
898 return type::from_value(rhs);
899}
900
901/// runtime unit divided by scalar
902template<class System,
903 class Dim,
904 class Y>
905inline
906typename divide_typeof_helper< unit<Dim,System>,Y >::type
907operator/(const unit<Dim,System>&,const Y& rhs)
908{
909 typedef typename divide_typeof_helper<unit<Dim,System>,Y>::type type;
910
911 return type::from_value(Y(1)/rhs);
912}
913
914/// runtime scalar times unit
915template<class System,
916 class Dim,
917 class Y>
918inline
919typename multiply_typeof_helper< Y,unit<Dim,System> >::type
920operator*(const Y& lhs,const unit<Dim,System>&)
921{
922 typedef typename multiply_typeof_helper< Y,unit<Dim,System> >::type type;
923
924 return type::from_value(lhs);
925}
926
927/// runtime scalar divided by unit
928template<class System,
929 class Dim,
930 class Y>
931inline
932typename divide_typeof_helper< Y,unit<Dim,System> >::type
933operator/(const Y& lhs,const unit<Dim,System>&)
934{
935 typedef typename divide_typeof_helper< Y,unit<Dim,System> >::type type;
936
937 return type::from_value(lhs);
938}
939
940///// runtime quantity times scalar
941//template<class Unit,
942// class X,
943// class Y>
944//inline
945//typename multiply_typeof_helper< quantity<Unit,X>,Y >::type
946//operator*(const quantity<Unit,X>& lhs,const Y& rhs)
947//{
948// typedef typename multiply_typeof_helper< quantity<Unit,X>,Y >::type type;
949//
950// return type::from_value(lhs.value()*rhs);
951//}
952//
953///// runtime scalar times quantity
954//template<class Unit,
955// class X,
956// class Y>
957//inline
958//typename multiply_typeof_helper< X,quantity<Unit,Y> >::type
959//operator*(const X& lhs,const quantity<Unit,Y>& rhs)
960//{
961// typedef typename multiply_typeof_helper< X,quantity<Unit,Y> >::type type;
962//
963// return type::from_value(lhs*rhs.value());
964//}
965
966/// runtime quantity times scalar
967template<class Unit,
968 class X>
969inline
970typename multiply_typeof_helper< quantity<Unit,X>,X >::type
971operator*(const quantity<Unit,X>& lhs,const X& rhs)
972{
973 typedef typename multiply_typeof_helper< quantity<Unit,X>,X >::type type;
974
975 return type::from_value(lhs.value()*rhs);
976}
977
978/// runtime scalar times quantity
979template<class Unit,
980 class X>
981inline
982typename multiply_typeof_helper< X,quantity<Unit,X> >::type
983operator*(const X& lhs,const quantity<Unit,X>& rhs)
984{
985 typedef typename multiply_typeof_helper< X,quantity<Unit,X> >::type type;
986
987 return type::from_value(lhs*rhs.value());
988}
989
990///// runtime quantity divided by scalar
991//template<class Unit,
992// class X,
993// class Y>
994//inline
995//typename divide_typeof_helper< quantity<Unit,X>,Y >::type
996//operator/(const quantity<Unit,X>& lhs,const Y& rhs)
997//{
998// typedef typename divide_typeof_helper< quantity<Unit,X>,Y >::type type;
999//
1000// return type::from_value(lhs.value()/rhs);
1001//}
1002//
1003///// runtime scalar divided by quantity
1004//template<class Unit,
1005// class X,
1006// class Y>
1007//inline
1008//typename divide_typeof_helper< X,quantity<Unit,Y> >::type
1009//operator/(const X& lhs,const quantity<Unit,Y>& rhs)
1010//{
1011// typedef typename divide_typeof_helper< X,quantity<Unit,Y> >::type type;
1012//
1013// return type::from_value(lhs/rhs.value());
1014//}
1015
1016/// runtime quantity divided by scalar
1017template<class Unit,
1018 class X>
1019inline
1020typename divide_typeof_helper< quantity<Unit,X>,X >::type
1021operator/(const quantity<Unit,X>& lhs,const X& rhs)
1022{
1023 typedef typename divide_typeof_helper< quantity<Unit,X>,X >::type type;
1024
1025 return type::from_value(lhs.value()/rhs);
1026}
1027
1028/// runtime scalar divided by quantity
1029template<class Unit,
1030 class X>
1031inline
1032typename divide_typeof_helper< X,quantity<Unit,X> >::type
1033operator/(const X& lhs,const quantity<Unit,X>& rhs)
1034{
1035 typedef typename divide_typeof_helper< X,quantity<Unit,X> >::type type;
1036
1037 return type::from_value(lhs/rhs.value());
1038}
1039
1040/// runtime unit times quantity
1041template<class System1,
1042 class Dim1,
1043 class Unit2,
1044 class Y>
1045inline
1046typename multiply_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type
1047operator*(const unit<Dim1,System1>&,const quantity<Unit2,Y>& rhs)
1048{
1049 typedef typename multiply_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type type;
1050
1051 return type::from_value(rhs.value());
1052}
1053
1054/// runtime unit divided by quantity
1055template<class System1,
1056 class Dim1,
1057 class Unit2,
1058 class Y>
1059inline
1060typename divide_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type
1061operator/(const unit<Dim1,System1>&,const quantity<Unit2,Y>& rhs)
1062{
1063 typedef typename divide_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type type;
1064
1065 return type::from_value(Y(1)/rhs.value());
1066}
1067
1068/// runtime quantity times unit
1069template<class Unit1,
1070 class System2,
1071 class Dim2,
1072 class Y>
1073inline
1074typename multiply_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type
1075operator*(const quantity<Unit1,Y>& lhs,const unit<Dim2,System2>&)
1076{
1077 typedef typename multiply_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type type;
1078
1079 return type::from_value(lhs.value());
1080}
1081
1082/// runtime quantity divided by unit
1083template<class Unit1,
1084 class System2,
1085 class Dim2,
1086 class Y>
1087inline
1088typename divide_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type
1089operator/(const quantity<Unit1,Y>& lhs,const unit<Dim2,System2>&)
1090{
1091 typedef typename divide_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type type;
1092
1093 return type::from_value(lhs.value());
1094}
1095
1096/// runtime unary plus quantity
1097template<class Unit,class Y>
1098typename unary_plus_typeof_helper< quantity<Unit,Y> >::type
1099operator+(const quantity<Unit,Y>& val)
1100{
1101 typedef typename unary_plus_typeof_helper< quantity<Unit,Y> >::type type;
1102
1103 return type::from_value(+val.value());
1104}
1105
1106/// runtime unary minus quantity
1107template<class Unit,class Y>
1108typename unary_minus_typeof_helper< quantity<Unit,Y> >::type
1109operator-(const quantity<Unit,Y>& val)
1110{
1111 typedef typename unary_minus_typeof_helper< quantity<Unit,Y> >::type type;
1112
1113 return type::from_value(-val.value());
1114}
1115
1116/// runtime quantity plus quantity
1117template<class Unit1,
1118 class Unit2,
1119 class X,
1120 class Y>
1121inline
1122typename add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1123operator+(const quantity<Unit1,X>& lhs,
1124 const quantity<Unit2,Y>& rhs)
1125{
1126 typedef typename add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type type;
1127
1128 return type::from_value(lhs.value()+rhs.value());
1129}
1130
1131/// runtime quantity minus quantity
1132template<class Unit1,
1133 class Unit2,
1134 class X,
1135 class Y>
1136inline
1137typename subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1138operator-(const quantity<Unit1,X>& lhs,
1139 const quantity<Unit2,Y>& rhs)
1140{
1141 typedef typename subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type type;
1142
1143 return type::from_value(lhs.value()-rhs.value());
1144}
1145
1146/// runtime quantity times quantity
1147template<class Unit1,
1148 class Unit2,
1149 class X,
1150 class Y>
1151inline
1152typename multiply_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1153operator*(const quantity<Unit1,X>& lhs,
1154 const quantity<Unit2,Y>& rhs)
1155{
1156 typedef typename multiply_typeof_helper< quantity<Unit1,X>,
1157 quantity<Unit2,Y> >::type type;
1158
1159 return type::from_value(lhs.value()*rhs.value());
1160}
1161
1162/// runtime quantity divided by quantity
1163template<class Unit1,
1164 class Unit2,
1165 class X,
1166 class Y>
1167inline
1168typename divide_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type
1169operator/(const quantity<Unit1,X>& lhs,
1170 const quantity<Unit2,Y>& rhs)
1171{
1172 typedef typename divide_typeof_helper< quantity<Unit1,X>,
1173 quantity<Unit2,Y> >::type type;
1174
1175 return type::from_value(lhs.value()/rhs.value());
1176}
1177
1178/// runtime operator==
1179template<class Unit,
1180 class X,
1181 class Y>
1182inline
1183bool
1184operator==(const quantity<Unit,X>& val1,
1185 const quantity<Unit,Y>& val2)
1186{
1187 return val1.value() == val2.value();
1188}
1189
1190/// runtime operator!=
1191template<class Unit,
1192 class X,
1193 class Y>
1194inline
1195bool
1196operator!=(const quantity<Unit,X>& val1,
1197 const quantity<Unit,Y>& val2)
1198{
1199 return val1.value() != val2.value();
1200}
1201
1202/// runtime operator<
1203template<class Unit,
1204 class X,
1205 class Y>
1206inline
1207bool
1208operator<(const quantity<Unit,X>& val1,
1209 const quantity<Unit,Y>& val2)
1210{
1211 return val1.value() < val2.value();
1212}
1213
1214/// runtime operator<=
1215template<class Unit,
1216 class X,
1217 class Y>
1218inline
1219bool
1220operator<=(const quantity<Unit,X>& val1,
1221 const quantity<Unit,Y>& val2)
1222{
1223 return val1.value() <= val2.value();
1224}
1225
1226/// runtime operator>
1227template<class Unit,
1228 class X,
1229 class Y>
1230inline
1231bool
1232operator>(const quantity<Unit,X>& val1,
1233 const quantity<Unit,Y>& val2)
1234{
1235 return val1.value() > val2.value();
1236}
1237
1238/// runtime operator>=
1239template<class Unit,
1240 class X,
1241 class Y>
1242inline
1243bool
1244operator>=(const quantity<Unit,X>& val1,
1245 const quantity<Unit,Y>& val2)
1246{
1247 return val1.value() >= val2.value();
1248}
1249
1250} // namespace units
1251
1252} // namespace boost
1253
1254#endif // BOOST_UNITS_QUANTITY_HPP
1255

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