1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and
2 // unit/quantity manipulation and conversion
4 // Copyright (C) 2003-2008 Matthias Christian Schabel
5 // Copyright (C) 2008 Steven Watanabe
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)
11 #ifndef BOOST_UNITS_UNIT_HPP
12 #define BOOST_UNITS_UNIT_HPP
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>
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>
33 /// class representing a model-dependent unit with no associated value
35 /// (e.g. meters, Kelvin, feet, etc...)
36 template<class Dim,class System, class Enable>
40 typedef unit<Dim, System> unit_type;
41 typedef unit<Dim,System> this_type;
42 typedef Dim dimension_type;
43 typedef System system_type;
46 unit(const this_type&) { }
49 this_type& operator=(const this_type&) { return *this; }
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.
57 BOOST_MPL_ASSERT((detail::check_system<System, Dim>));
58 BOOST_MPL_ASSERT((is_dimension_list<Dim>));
62 BOOST_MPL_ASSERT((detail::check_system<System, Dim>));
63 BOOST_MPL_ASSERT((is_dimension_list<Dim>));
71 #if BOOST_UNITS_HAS_BOOST_TYPEOF
73 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
75 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::units::unit, 2)
83 /// Returns a unique type for every unit.
84 template<class Dim, class System>
85 struct reduce_unit<unit<Dim, System> >
89 typename detail::make_heterogeneous_system<
97 template<class S1,class S2>
98 struct is_implicitly_convertible :
99 boost::is_same<typename reduce_unit<S1>::type, typename reduce_unit<S2>::type>
102 /// unit unary plus typeof helper
104 template<class Dim,class System>
105 struct unary_plus_typeof_helper< unit<Dim,System> >
107 typedef unit<Dim,System> type;
110 /// unit unary minus typeof helper
112 template<class Dim,class System>
113 struct unary_minus_typeof_helper< unit<Dim,System> >
115 typedef unit<Dim,System> type;
118 /// unit add typeof helper
122 struct add_typeof_helper< unit<Dim,System>,unit<Dim,System> >
124 typedef unit<Dim,System> type;
127 /// unit subtract typeof helper
131 struct subtract_typeof_helper< unit<Dim,System>,unit<Dim,System> >
133 typedef unit<Dim,System> type;
136 /// unit multiply typeof helper for two identical homogeneous systems
141 struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System> >,
142 unit<Dim2,homogeneous_system<System> > >
144 typedef unit<typename mpl::times<Dim1,Dim2>::type,homogeneous_system<System> > type;
147 /// unit multiply typeof helper for two different homogeneous systems
153 struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
154 unit<Dim2,homogeneous_system<System2> > >
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
165 /// unit multiply typeof helper for a heterogeneous and a homogeneous system
171 struct multiply_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
172 unit<Dim2,homogeneous_system<System2> > >
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
183 /// unit multiply typeof helper for a homogeneous and a heterogeneous system
189 struct multiply_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
190 unit<Dim2,heterogeneous_system<System2> > >
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>
201 /// unit multiply typeof helper for two heterogeneous systems
207 struct multiply_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
208 unit<Dim2,heterogeneous_system<System2> > >
211 typename mpl::times<Dim1,Dim2>::type,
212 typename detail::multiply_systems<
213 heterogeneous_system<System1>,
214 heterogeneous_system<System2>
219 /// unit divide typeof helper for two identical homogeneous systems
224 struct divide_typeof_helper< unit<Dim1,homogeneous_system<System> >,
225 unit<Dim2,homogeneous_system<System> > >
227 typedef unit<typename mpl::divides<Dim1,Dim2>::type,homogeneous_system<System> > type;
230 /// unit divide typeof helper for two different homogeneous systems
236 struct divide_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
237 unit<Dim2,homogeneous_system<System2> > >
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
248 /// unit divide typeof helper for a heterogeneous and a homogeneous system
254 struct divide_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
255 unit<Dim2,homogeneous_system<System2> > >
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
266 /// unit divide typeof helper for a homogeneous and a heterogeneous system
272 struct divide_typeof_helper< unit<Dim1,homogeneous_system<System1> >,
273 unit<Dim2,heterogeneous_system<System2> > >
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>
284 /// unit divide typeof helper for two heterogeneous systems
290 struct divide_typeof_helper< unit<Dim1,heterogeneous_system<System1> >,
291 unit<Dim2,heterogeneous_system<System2> > >
294 typename mpl::divides<Dim1,Dim2>::type,
295 typename detail::divide_systems<
296 heterogeneous_system<System1>,
297 heterogeneous_system<System2>
302 /// raise unit to a @c static_rational power
303 template<class Dim,class System,long N,long D>
304 struct power_typeof_helper<unit<Dim,System>,static_rational<N,D> >
306 typedef unit<typename static_power<Dim,static_rational<N,D> >::type,typename static_power<System, static_rational<N,D> >::type> type;
308 static type value(const unit<Dim,System>&)
314 /// take the @c static_rational root of a unit
315 template<class Dim,class System,long N,long D>
316 struct root_typeof_helper<unit<Dim,System>,static_rational<N,D> >
318 typedef unit<typename static_root<Dim,static_rational<N,D> >::type,typename static_root<System, static_rational<N,D> >::type> type;
320 static type value(const unit<Dim,System>&)
326 /// unit runtime unary plus
327 template<class Dim,class System>
328 typename unary_plus_typeof_helper< unit<Dim,System> >::type
329 operator+(const unit<Dim,System>&)
331 typedef typename unary_plus_typeof_helper< unit<Dim,System> >::type type;
336 /// unit runtime unary minus
337 template<class Dim,class System>
338 typename unary_minus_typeof_helper< unit<Dim,System> >::type
339 operator-(const unit<Dim,System>&)
341 typedef typename unary_minus_typeof_helper< unit<Dim,System> >::type type;
346 /// runtime add two units
351 typename add_typeof_helper< unit<Dim1,System1>,
352 unit<Dim2,System2> >::type
353 operator+(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
355 BOOST_STATIC_ASSERT((boost::is_same<System1,System2>::value == true));
357 typedef System1 system_type;
358 typedef typename add_typeof_helper< unit<Dim1,system_type>,
359 unit<Dim2,system_type> >::type type;
364 /// runtime subtract two units
369 typename subtract_typeof_helper< unit<Dim1,System1>,
370 unit<Dim2,System2> >::type
371 operator-(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
373 BOOST_STATIC_ASSERT((boost::is_same<System1,System2>::value == true));
375 typedef System1 system_type;
376 typedef typename subtract_typeof_helper< unit<Dim1,system_type>,
377 unit<Dim2,system_type> >::type type;
382 /// runtime multiply two units
387 typename multiply_typeof_helper< unit<Dim1,System1>,
388 unit<Dim2,System2> >::type
389 operator*(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
391 typedef typename multiply_typeof_helper< unit<Dim1,System1>,
392 unit<Dim2,System2> >::type type;
397 /// runtime divide two units
402 typename divide_typeof_helper< unit<Dim1,System1>,
403 unit<Dim2,System2> >::type
404 operator/(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
406 typedef typename divide_typeof_helper< unit<Dim1,System1>,
407 unit<Dim2,System2> >::type type;
412 /// unit runtime @c operator==
419 operator==(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
421 return boost::is_same<typename reduce_unit<unit<Dim1,System1> >::type, typename reduce_unit<unit<Dim2,System2> >::type>::value;
424 /// unit runtime @c operator!=
431 operator!=(const unit<Dim1,System1>&,const unit<Dim2,System2>&)
433 return !boost::is_same<typename reduce_unit<unit<Dim1,System1> >::type, typename reduce_unit<unit<Dim2,System2> >::type>::value;
440 #endif // BOOST_UNITS_UNIT_HPP