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_OPERATORS_HPP
12 #define BOOST_UNITS_OPERATORS_HPP
13 
14 
15 ///
16 /// \file
17 /// \brief Compile time operators and typeof helper classes.
18 /// \details
19 ///   These operators declare the compile-time operators needed to support dimensional
20 ///   analysis algebra.  They require the use of Boost.Typeof, emulation or native.
21 ///   Typeof helper classes define result type for heterogeneous operators on value types.
22 ///   These must be defined through specialization for powers and roots.
23 ///
24 
25 #include <boost/static_assert.hpp>
26 #include <boost/type_traits/is_same.hpp>
27 
28 #include <boost/units/config.hpp>
29 
30 namespace boost {
31 namespace units {
32 
33 #if BOOST_UNITS_HAS_TYPEOF
34 
35 #ifndef BOOST_UNITS_DOXYGEN
36 
37 // to avoid need for default constructor and eliminate divide by zero errors.
38 namespace typeof_ {
39 
40 /// INTERNAL ONLY
41 template<class T> T make();
42 
43 } // namespace typeof_
44 
45 #endif
46 
47 #if (BOOST_UNITS_HAS_BOOST_TYPEOF)
48 
49 template<typename X> struct unary_plus_typeof_helper
50 {
51     BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, (+typeof_::make<X>()))
52     typedef typename nested::type type;
53 };
54 
55 template<typename X> struct unary_minus_typeof_helper
56 {
57     BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, (-typeof_::make<X>()))
58     typedef typename nested::type type;
59 };
60 
61 template<typename X,typename Y> struct add_typeof_helper
62 {
63     BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, (typeof_::make<X>()+typeof_::make<Y>()))
64     typedef typename nested::type type;
65 };
66 
67 template<typename X,typename Y> struct subtract_typeof_helper
68 {
69     BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, (typeof_::make<X>()-typeof_::make<Y>()))
70     typedef typename nested::type type;
71 };
72 
73 template<typename X,typename Y> struct multiply_typeof_helper
74 {
75     BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, (typeof_::make<X>()*typeof_::make<Y>()))
76     typedef typename nested::type type;
77 };
78 
79 template<typename X,typename Y> struct divide_typeof_helper
80 {
81     BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, (typeof_::make<X>()/typeof_::make<Y>()))
82     typedef typename nested::type type;
83 };
84 
85 #elif (BOOST_UNITS_HAS_MWERKS_TYPEOF)
86 
87 template<typename X> struct unary_plus_typeof_helper            { typedef __typeof__((+typeof_::make<X>())) type; };
88 template<typename X> struct unary_minus_typeof_helper           { typedef __typeof__((-typeof_::make<X>())) type; };
89 
90 template<typename X,typename Y> struct add_typeof_helper        { typedef __typeof__((typeof_::make<X>()+typeof_::make<Y>())) type; };
91 template<typename X,typename Y> struct subtract_typeof_helper   { typedef __typeof__((typeof_::make<X>()-typeof_::make<Y>())) type; };
92 template<typename X,typename Y> struct multiply_typeof_helper   { typedef __typeof__((typeof_::make<X>()*typeof_::make<Y>())) type; };
93 template<typename X,typename Y> struct divide_typeof_helper     { typedef __typeof__((typeof_::make<X>()/typeof_::make<Y>())) type; };
94 
95 #elif (BOOST_UNITS_HAS_GNU_TYPEOF) || defined(BOOST_UNITS_DOXYGEN)
96 
97 template<typename X> struct unary_plus_typeof_helper            { typedef typeof((+typeof_::make<X>())) type; };
98 template<typename X> struct unary_minus_typeof_helper           { typedef typeof((-typeof_::make<X>())) type; };
99 
100 template<typename X,typename Y> struct add_typeof_helper        { typedef typeof((typeof_::make<X>()+typeof_::make<Y>())) type; };
101 template<typename X,typename Y> struct subtract_typeof_helper   { typedef typeof((typeof_::make<X>()-typeof_::make<Y>())) type; };
102 template<typename X,typename Y> struct multiply_typeof_helper   { typedef typeof((typeof_::make<X>()*typeof_::make<Y>())) type; };
103 template<typename X,typename Y> struct divide_typeof_helper     { typedef typeof((typeof_::make<X>()/typeof_::make<Y>())) type; };
104 
105 #endif
106 
107 #else // BOOST_UNITS_HAS_TYPEOF
108 
109 template<typename X> struct unary_plus_typeof_helper            { typedef X type; };
110 template<typename X> struct unary_minus_typeof_helper           { typedef X type; };
111 
112 template<typename X,typename Y> struct add_typeof_helper        { BOOST_STATIC_ASSERT((is_same<X,Y>::value == true)); typedef X type; };
113 template<typename X,typename Y> struct subtract_typeof_helper   { BOOST_STATIC_ASSERT((is_same<X,Y>::value == true)); typedef X type; };
114 template<typename X,typename Y> struct multiply_typeof_helper   { BOOST_STATIC_ASSERT((is_same<X,Y>::value == true)); typedef X type; };
115 template<typename X,typename Y> struct divide_typeof_helper     { BOOST_STATIC_ASSERT((is_same<X,Y>::value == true)); typedef X type; };
116 
117 #endif // BOOST_UNITS_HAS_TYPEOF
118 
119 template<typename X,typename Y> struct power_typeof_helper;
120 template<typename X,typename Y> struct root_typeof_helper;
121 
122 #ifdef BOOST_UNITS_DOXYGEN
123 
124 /// A helper used by @c pow to raise
125 /// a runtime object to a compile time
126 /// known exponent.  This template is intended to
127 /// be specialized.  All specializations must
128 /// conform to the interface shown here.
129 /// @c Exponent will be either the exponent
130 /// passed to @c pow or @c static_rational<N>
131 /// for and integer argument, N.
132 template<typename BaseType, typename Exponent>
133 struct power_typeof_helper
134 {
135     /// specifies the result type
136     typedef detail::unspecified type;
137     /// Carries out the runtime calculation.
138     static BOOST_CONSTEXPR type value(const BaseType& base);
139 };
140 
141 /// A helper used by @c root to take a root
142 /// of a runtime object using a compile time
143 /// known index.  This template is intended to
144 /// be specialized.  All specializations must
145 /// conform to the interface shown here.
146 /// @c Index will be either the type
147 /// passed to @c pow or @c static_rational<N>
148 /// for and integer argument, N.
149 template<typename Radicand, typename Index>
150 struct root_typeof_helper
151 {
152     /// specifies the result type
153     typedef detail::unspecified type;
154     /// Carries out the runtime calculation.
155     static BOOST_CONSTEXPR type value(const Radicand& base);
156 };
157 
158 #endif
159 
160 } // namespace units
161 
162 } // namespace boost
163 
164 #endif // BOOST_UNITS_OPERATORS_HPP
165