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 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 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 | |