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 | |
37 | namespace boost { |
38 | |
39 | namespace units { |
40 | |
41 | namespace detail { |
42 | |
43 | template<class T, class Enable = void> |
44 | struct is_base_unit : mpl::false_ {}; |
45 | |
46 | template<class T> |
47 | struct is_base_unit<T, typename T::boost_units_is_base_unit_type> : mpl::true_ {}; |
48 | |
49 | template<class Source, class Destination> |
50 | struct is_narrowing_conversion_impl : mpl::bool_<(sizeof(Source) > sizeof(Destination))> {}; |
51 | |
52 | template<class Source, class Destination> |
53 | struct 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 | |
72 | template<> |
73 | struct is_non_narrowing_conversion<long double, double> : mpl::false_ {}; |
74 | |
75 | // msvc 7.1 needs extra disambiguation |
76 | template<class T, class U> |
77 | struct disable_if_is_same |
78 | { |
79 | typedef void type; |
80 | }; |
81 | |
82 | template<class T> |
83 | struct disable_if_is_same<T, T> {}; |
84 | |
85 | } |
86 | |
87 | /// class declaration |
88 | template<class Unit,class Y> |
89 | class 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. |
297 | template<class System,class Y> |
298 | class 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 |
483 | template<class System, class T> |
484 | class quantity<unit<int, System>, T> {}; |
485 | template<class T> |
486 | class 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 | |
497 | BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::quantity, 2) |
498 | |
499 | #endif |
500 | |
501 | namespace boost { |
502 | |
503 | namespace units { |
504 | |
505 | namespace detail { |
506 | |
507 | /// helper class for quantity_cast |
508 | template<class X,class Y> struct quantity_cast_helper; |
509 | |
510 | /// specialization for casting to the value type |
511 | template<class Y,class X,class Unit> |
512 | struct 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 |
520 | template<class Y,class X,class Unit> |
521 | struct 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 |
531 | template<class X,class Y> |
532 | inline |
533 | X |
534 | quantity_cast(Y& source) |
535 | { |
536 | detail::quantity_cast_helper<X,Y> qch; |
537 | |
538 | return qch(source); |
539 | } |
540 | |
541 | template<class X,class Y> |
542 | inline |
543 | X |
544 | quantity_cast(const Y& source) |
545 | { |
546 | detail::quantity_cast_helper<X,const Y> qch; |
547 | |
548 | return qch(source); |
549 | } |
550 | |
551 | /// swap quantities |
552 | template<class Unit,class Y> |
553 | inline 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 |
561 | template<class Unit,class Y> |
562 | struct 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 |
571 | template<class Unit,class Y> |
572 | struct 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 |
581 | template<class Unit1, |
582 | class Unit2, |
583 | class X, |
584 | class Y> |
585 | struct 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. |
595 | template<class Dim1, class System1, |
596 | class Dim2, class System2, |
597 | class X, |
598 | class Y> |
599 | struct add_typeof_helper< quantity<unit<Dim1, System1>,X>,quantity<unit<Dim2, System2>,Y> > |
600 | { |
601 | }; |
602 | |
603 | template<class Dim, |
604 | class System, |
605 | class X, |
606 | class Y> |
607 | struct 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 |
616 | template<class Unit1, |
617 | class Unit2, |
618 | class X, |
619 | class Y> |
620 | struct 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. |
628 | template<class Dim1, class System1, |
629 | class Dim2, class System2, |
630 | class X, |
631 | class Y> |
632 | struct subtract_typeof_helper< quantity<unit<Dim1, System1>,X>,quantity<unit<Dim2, System2>,Y> > |
633 | { |
634 | }; |
635 | |
636 | template<class Dim, |
637 | class System, |
638 | class X, |
639 | class Y> |
640 | struct 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 |
649 | template<class System, |
650 | class Dim, |
651 | class X> |
652 | struct 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 |
661 | template<class System, |
662 | class Dim, |
663 | class X> |
664 | struct 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 |
673 | template<class Unit, |
674 | class X, |
675 | class Y> |
676 | struct 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 |
685 | template<class Unit, |
686 | class Y> |
687 | struct 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 |
694 | template<class Unit, |
695 | class X, |
696 | class Y> |
697 | struct 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 |
706 | template<class Unit, |
707 | class X> |
708 | struct 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 |
715 | template<class Unit, |
716 | class System, |
717 | class Dim, |
718 | class X> |
719 | struct 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 |
728 | template<class Unit, |
729 | class System, |
730 | class Dim, |
731 | class X> |
732 | struct 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 |
741 | template<class Unit1, |
742 | class Unit2, |
743 | class X, |
744 | class Y> |
745 | struct 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 |
754 | template<class System, |
755 | class Dim, |
756 | class X> |
757 | struct 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 |
766 | template<class System, |
767 | class Dim, |
768 | class X> |
769 | struct 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 |
778 | template<class Unit, |
779 | class X, |
780 | class Y> |
781 | struct 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 |
790 | template<class Unit, |
791 | class Y> |
792 | struct 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 |
799 | template<class Unit, |
800 | class X, |
801 | class Y> |
802 | struct 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 |
811 | template<class Unit, |
812 | class X> |
813 | struct 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 |
820 | template<class Unit, |
821 | class System, |
822 | class Dim, |
823 | class X> |
824 | struct 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 |
833 | template<class Unit, |
834 | class System, |
835 | class Dim, |
836 | class X> |
837 | struct 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 |
846 | template<class Unit1, |
847 | class Unit2, |
848 | class X, |
849 | class Y> |
850 | struct 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 |
859 | template<class Unit,long N,long D,class Y> |
860 | struct 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 |
874 | template<class Unit,long N,long D,class Y> |
875 | struct 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 |
889 | template<class System, |
890 | class Dim, |
891 | class Y> |
892 | inline |
893 | typename multiply_typeof_helper< unit<Dim,System>,Y >::type |
894 | operator*(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 |
902 | template<class System, |
903 | class Dim, |
904 | class Y> |
905 | inline |
906 | typename divide_typeof_helper< unit<Dim,System>,Y >::type |
907 | operator/(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 |
915 | template<class System, |
916 | class Dim, |
917 | class Y> |
918 | inline |
919 | typename multiply_typeof_helper< Y,unit<Dim,System> >::type |
920 | operator*(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 |
928 | template<class System, |
929 | class Dim, |
930 | class Y> |
931 | inline |
932 | typename divide_typeof_helper< Y,unit<Dim,System> >::type |
933 | operator/(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 |
967 | template<class Unit, |
968 | class X> |
969 | inline |
970 | typename multiply_typeof_helper< quantity<Unit,X>,X >::type |
971 | operator*(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 |
979 | template<class Unit, |
980 | class X> |
981 | inline |
982 | typename multiply_typeof_helper< X,quantity<Unit,X> >::type |
983 | operator*(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 |
1017 | template<class Unit, |
1018 | class X> |
1019 | inline |
1020 | typename divide_typeof_helper< quantity<Unit,X>,X >::type |
1021 | operator/(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 |
1029 | template<class Unit, |
1030 | class X> |
1031 | inline |
1032 | typename divide_typeof_helper< X,quantity<Unit,X> >::type |
1033 | operator/(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 |
1041 | template<class System1, |
1042 | class Dim1, |
1043 | class Unit2, |
1044 | class Y> |
1045 | inline |
1046 | typename multiply_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type |
1047 | operator*(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 |
1055 | template<class System1, |
1056 | class Dim1, |
1057 | class Unit2, |
1058 | class Y> |
1059 | inline |
1060 | typename divide_typeof_helper< unit<Dim1,System1>,quantity<Unit2,Y> >::type |
1061 | operator/(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 |
1069 | template<class Unit1, |
1070 | class System2, |
1071 | class Dim2, |
1072 | class Y> |
1073 | inline |
1074 | typename multiply_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type |
1075 | operator*(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 |
1083 | template<class Unit1, |
1084 | class System2, |
1085 | class Dim2, |
1086 | class Y> |
1087 | inline |
1088 | typename divide_typeof_helper< quantity<Unit1,Y>,unit<Dim2,System2> >::type |
1089 | operator/(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 |
1097 | template<class Unit,class Y> |
1098 | typename unary_plus_typeof_helper< quantity<Unit,Y> >::type |
1099 | operator+(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 |
1107 | template<class Unit,class Y> |
1108 | typename unary_minus_typeof_helper< quantity<Unit,Y> >::type |
1109 | operator-(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 |
1117 | template<class Unit1, |
1118 | class Unit2, |
1119 | class X, |
1120 | class Y> |
1121 | inline |
1122 | typename add_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type |
1123 | operator+(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 |
1132 | template<class Unit1, |
1133 | class Unit2, |
1134 | class X, |
1135 | class Y> |
1136 | inline |
1137 | typename subtract_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type |
1138 | operator-(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 |
1147 | template<class Unit1, |
1148 | class Unit2, |
1149 | class X, |
1150 | class Y> |
1151 | inline |
1152 | typename multiply_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type |
1153 | operator*(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 |
1163 | template<class Unit1, |
1164 | class Unit2, |
1165 | class X, |
1166 | class Y> |
1167 | inline |
1168 | typename divide_typeof_helper< quantity<Unit1,X>,quantity<Unit2,Y> >::type |
1169 | operator/(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== |
1179 | template<class Unit, |
1180 | class X, |
1181 | class Y> |
1182 | inline |
1183 | bool |
1184 | operator==(const quantity<Unit,X>& val1, |
1185 | const quantity<Unit,Y>& val2) |
1186 | { |
1187 | return val1.value() == val2.value(); |
1188 | } |
1189 | |
1190 | /// runtime operator!= |
1191 | template<class Unit, |
1192 | class X, |
1193 | class Y> |
1194 | inline |
1195 | bool |
1196 | operator!=(const quantity<Unit,X>& val1, |
1197 | const quantity<Unit,Y>& val2) |
1198 | { |
1199 | return val1.value() != val2.value(); |
1200 | } |
1201 | |
1202 | /// runtime operator< |
1203 | template<class Unit, |
1204 | class X, |
1205 | class Y> |
1206 | inline |
1207 | bool |
1208 | operator<(const quantity<Unit,X>& val1, |
1209 | const quantity<Unit,Y>& val2) |
1210 | { |
1211 | return val1.value() < val2.value(); |
1212 | } |
1213 | |
1214 | /// runtime operator<= |
1215 | template<class Unit, |
1216 | class X, |
1217 | class Y> |
1218 | inline |
1219 | bool |
1220 | operator<=(const quantity<Unit,X>& val1, |
1221 | const quantity<Unit,Y>& val2) |
1222 | { |
1223 | return val1.value() <= val2.value(); |
1224 | } |
1225 | |
1226 | /// runtime operator> |
1227 | template<class Unit, |
1228 | class X, |
1229 | class Y> |
1230 | inline |
1231 | bool |
1232 | operator>(const quantity<Unit,X>& val1, |
1233 | const quantity<Unit,Y>& val2) |
1234 | { |
1235 | return val1.value() > val2.value(); |
1236 | } |
1237 | |
1238 | /// runtime operator>= |
1239 | template<class Unit, |
1240 | class X, |
1241 | class Y> |
1242 | inline |
1243 | bool |
1244 | operator>=(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 | |