|
4 | 4 | #include <cmath>
|
5 | 5 | #include <ratio>
|
6 | 6 | #include <iostream>
|
| 7 | +#include <type_traits> |
7 | 8 | #include <utility>
|
8 | 9 | #include <algorithm>
|
9 | 10 |
|
@@ -114,6 +115,21 @@ class Quantity {
|
114 | 115 | }
|
115 | 116 | };
|
116 | 117 |
|
| 118 | +/* Number is a special type, because it can be implicitly converted to and from any arithmetic type */ |
| 119 | +class Number : public Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, |
| 120 | + std::ratio<0>, std::ratio<0>> { |
| 121 | + public: |
| 122 | + template <typename T> constexpr Number(T value) |
| 123 | + : Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, |
| 124 | + std::ratio<0>, std::ratio<0>>(double(value)) {} |
| 125 | + |
| 126 | + constexpr Number(Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, |
| 127 | + std::ratio<0>, std::ratio<0>, std::ratio<0>> |
| 128 | + value) |
| 129 | + : Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, |
| 130 | + std::ratio<0>, std::ratio<0>>(value) {}; |
| 131 | +}; |
| 132 | + |
117 | 133 | template <typename Q> struct LookupName {
|
118 | 134 | using Named = Q;
|
119 | 135 | };
|
@@ -221,12 +237,18 @@ template <isQuantity Q> constexpr Q operator*(double multiple, Q quantity) { ret
|
221 | 237 |
|
222 | 238 | template <isQuantity Q> constexpr Q operator/(Q quantity, double divisor) { return Q(quantity.internal() / divisor); }
|
223 | 239 |
|
224 |
| -template <isQuantity Q1, isQuantity Q2, isQuantity Q3 = Multiplied<Q1, Q2>> Q3 constexpr operator*(Q1 lhs, Q2 rhs) { |
225 |
| - return Q3(lhs.internal() * rhs.internal()); |
| 240 | +template <isQuantity Q1, isQuantity Q2> |
| 241 | +std::conditional_t<std::is_same_v<Number, Multiplied<Q1, Q2>>, double, Multiplied<Q1, Q2>> constexpr operator*(Q1 lhs, |
| 242 | + Q2 rhs) { |
| 243 | + return std::conditional_t<std::is_same_v<Number, Multiplied<Q1, Q2>>, double, Multiplied<Q1, Q2>>(lhs.internal() * |
| 244 | + rhs.internal()); |
226 | 245 | }
|
227 | 246 |
|
228 |
| -template <isQuantity Q1, isQuantity Q2, isQuantity Q3 = Divided<Q1, Q2>> Q3 constexpr operator/(Q1 lhs, Q2 rhs) { |
229 |
| - return Q3(lhs.internal() / rhs.internal()); |
| 247 | +template <isQuantity Q1, isQuantity Q2> |
| 248 | +std::conditional_t<std::is_same_v<Number, Multiplied<Q1, Q2>>, double, Divided<Q1, Q2>> constexpr operator/(Q1 lhs, |
| 249 | + Q2 rhs) { |
| 250 | + return std::conditional_t<std::is_same_v<Number, Multiplied<Q1, Q2>>, double, Divided<Q1, Q2>>(lhs.internal() / |
| 251 | + rhs.internal()); |
230 | 252 | }
|
231 | 253 |
|
232 | 254 | template <isQuantity Q, isQuantity R> constexpr bool operator==(const Q& lhs, const R& rhs)
|
@@ -316,23 +338,6 @@ template <isQuantity Q, isQuantity R> constexpr bool operator>(const Q& lhs, con
|
316 | 338 | NEW_UNIT_LITERAL(Name, u##base, base / 1E6) \
|
317 | 339 | NEW_UNIT_LITERAL(Name, n##base, base / 1E9)
|
318 | 340 |
|
319 |
| -/* Number is a special type, because it can be implicitly converted to and from any arithmetic type */ |
320 |
| -class Number : public Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, |
321 |
| - std::ratio<0>, std::ratio<0>> { |
322 |
| - public: |
323 |
| - template <typename T> constexpr Number(T value) |
324 |
| - : Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, |
325 |
| - std::ratio<0>, std::ratio<0>>(double(value)) {} |
326 |
| - |
327 |
| - template <typename T> constexpr explicit operator T() { return T(value); } |
328 |
| - |
329 |
| - constexpr Number(Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, |
330 |
| - std::ratio<0>, std::ratio<0>, std::ratio<0>> |
331 |
| - value) |
332 |
| - : Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, |
333 |
| - std::ratio<0>, std::ratio<0>>(value) {}; |
334 |
| -}; |
335 |
| - |
336 | 341 | template <> struct LookupName<Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>,
|
337 | 342 | std::ratio<0>, std::ratio<0>, std::ratio<0>>> {
|
338 | 343 | using Named = Number;
|
|
0 commit comments