annotate osx/include/kj/units.h @ 140:59a8758c56b1

Add source for PortAudio stable v190600_20161030
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 03 Jan 2017 13:44:07 +0000
parents 41e769c91eca
children 0994c39f1e94
rev   line source
cannam@134 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
cannam@134 2 // Licensed under the MIT License:
cannam@134 3 //
cannam@134 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@134 5 // of this software and associated documentation files (the "Software"), to deal
cannam@134 6 // in the Software without restriction, including without limitation the rights
cannam@134 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@134 8 // copies of the Software, and to permit persons to whom the Software is
cannam@134 9 // furnished to do so, subject to the following conditions:
cannam@134 10 //
cannam@134 11 // The above copyright notice and this permission notice shall be included in
cannam@134 12 // all copies or substantial portions of the Software.
cannam@134 13 //
cannam@134 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@134 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@134 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@134 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@134 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@134 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@134 20 // THE SOFTWARE.
cannam@134 21
cannam@134 22 // This file contains types which are intended to help detect incorrect usage at compile
cannam@134 23 // time, but should then be optimized down to basic primitives (usually, integers) by the
cannam@134 24 // compiler.
cannam@134 25
cannam@134 26 #ifndef KJ_UNITS_H_
cannam@134 27 #define KJ_UNITS_H_
cannam@134 28
cannam@134 29 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
cannam@134 30 #pragma GCC system_header
cannam@134 31 #endif
cannam@134 32
cannam@134 33 #include "common.h"
cannam@134 34
cannam@134 35 namespace kj {
cannam@134 36
cannam@134 37 // =======================================================================================
cannam@134 38 // IDs
cannam@134 39
cannam@134 40 template <typename UnderlyingType, typename Label>
cannam@134 41 struct Id {
cannam@134 42 // A type-safe numeric ID. `UnderlyingType` is the underlying integer representation. `Label`
cannam@134 43 // distinguishes this Id from other Id types. Sample usage:
cannam@134 44 //
cannam@134 45 // class Foo;
cannam@134 46 // typedef Id<uint, Foo> FooId;
cannam@134 47 //
cannam@134 48 // class Bar;
cannam@134 49 // typedef Id<uint, Bar> BarId;
cannam@134 50 //
cannam@134 51 // You can now use the FooId and BarId types without any possibility of accidentally using a
cannam@134 52 // FooId when you really wanted a BarId or vice-versa.
cannam@134 53
cannam@134 54 UnderlyingType value;
cannam@134 55
cannam@134 56 inline constexpr Id(): value(0) {}
cannam@134 57 inline constexpr explicit Id(int value): value(value) {}
cannam@134 58
cannam@134 59 inline constexpr bool operator==(const Id& other) const { return value == other.value; }
cannam@134 60 inline constexpr bool operator!=(const Id& other) const { return value != other.value; }
cannam@134 61 inline constexpr bool operator<=(const Id& other) const { return value <= other.value; }
cannam@134 62 inline constexpr bool operator>=(const Id& other) const { return value >= other.value; }
cannam@134 63 inline constexpr bool operator< (const Id& other) const { return value < other.value; }
cannam@134 64 inline constexpr bool operator> (const Id& other) const { return value > other.value; }
cannam@134 65 };
cannam@134 66
cannam@134 67 // =======================================================================================
cannam@134 68 // Quantity and UnitRatio -- implement unit analysis via the type system
cannam@134 69
cannam@134 70 template <typename T> constexpr bool isIntegral() { return false; }
cannam@134 71 template <> constexpr bool isIntegral<char>() { return true; }
cannam@134 72 template <> constexpr bool isIntegral<signed char>() { return true; }
cannam@134 73 template <> constexpr bool isIntegral<short>() { return true; }
cannam@134 74 template <> constexpr bool isIntegral<int>() { return true; }
cannam@134 75 template <> constexpr bool isIntegral<long>() { return true; }
cannam@134 76 template <> constexpr bool isIntegral<long long>() { return true; }
cannam@134 77 template <> constexpr bool isIntegral<unsigned char>() { return true; }
cannam@134 78 template <> constexpr bool isIntegral<unsigned short>() { return true; }
cannam@134 79 template <> constexpr bool isIntegral<unsigned int>() { return true; }
cannam@134 80 template <> constexpr bool isIntegral<unsigned long>() { return true; }
cannam@134 81 template <> constexpr bool isIntegral<unsigned long long>() { return true; }
cannam@134 82
cannam@134 83 template <typename Number, typename Unit1, typename Unit2>
cannam@134 84 class UnitRatio {
cannam@134 85 // A multiplier used to convert Quantities of one unit to Quantities of another unit. See
cannam@134 86 // Quantity, below.
cannam@134 87 //
cannam@134 88 // Construct this type by dividing one Quantity by another of a different unit. Use this type
cannam@134 89 // by multiplying it by a Quantity, or dividing a Quantity by it.
cannam@134 90
cannam@134 91 static_assert(isIntegral<Number>(), "Underlying type for UnitRatio must be integer.");
cannam@134 92
cannam@134 93 public:
cannam@134 94 inline UnitRatio() {}
cannam@134 95
cannam@134 96 constexpr explicit UnitRatio(Number unit1PerUnit2): unit1PerUnit2(unit1PerUnit2) {}
cannam@134 97 // This constructor was intended to be private, but GCC complains about it being private in a
cannam@134 98 // bunch of places that don't appear to even call it, so I made it public. Oh well.
cannam@134 99
cannam@134 100 template <typename OtherNumber>
cannam@134 101 inline constexpr UnitRatio(const UnitRatio<OtherNumber, Unit1, Unit2>& other)
cannam@134 102 : unit1PerUnit2(other.unit1PerUnit2) {}
cannam@134 103
cannam@134 104 template <typename OtherNumber>
cannam@134 105 inline constexpr UnitRatio<decltype(Number(1)+OtherNumber(1)), Unit1, Unit2>
cannam@134 106 operator+(UnitRatio<OtherNumber, Unit1, Unit2> other) const {
cannam@134 107 return UnitRatio<decltype(Number(1)+OtherNumber(1)), Unit1, Unit2>(
cannam@134 108 unit1PerUnit2 + other.unit1PerUnit2);
cannam@134 109 }
cannam@134 110 template <typename OtherNumber>
cannam@134 111 inline constexpr UnitRatio<decltype(Number(1)-OtherNumber(1)), Unit1, Unit2>
cannam@134 112 operator-(UnitRatio<OtherNumber, Unit1, Unit2> other) const {
cannam@134 113 return UnitRatio<decltype(Number(1)-OtherNumber(1)), Unit1, Unit2>(
cannam@134 114 unit1PerUnit2 - other.unit1PerUnit2);
cannam@134 115 }
cannam@134 116
cannam@134 117 template <typename OtherNumber, typename Unit3>
cannam@134 118 inline constexpr UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit3, Unit2>
cannam@134 119 operator*(UnitRatio<OtherNumber, Unit3, Unit1> other) const {
cannam@134 120 // U1 / U2 * U3 / U1 = U3 / U2
cannam@134 121 return UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit3, Unit2>(
cannam@134 122 unit1PerUnit2 * other.unit1PerUnit2);
cannam@134 123 }
cannam@134 124 template <typename OtherNumber, typename Unit3>
cannam@134 125 inline constexpr UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit1, Unit3>
cannam@134 126 operator*(UnitRatio<OtherNumber, Unit2, Unit3> other) const {
cannam@134 127 // U1 / U2 * U2 / U3 = U1 / U3
cannam@134 128 return UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit1, Unit3>(
cannam@134 129 unit1PerUnit2 * other.unit1PerUnit2);
cannam@134 130 }
cannam@134 131
cannam@134 132 template <typename OtherNumber, typename Unit3>
cannam@134 133 inline constexpr UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit3, Unit2>
cannam@134 134 operator/(UnitRatio<OtherNumber, Unit1, Unit3> other) const {
cannam@134 135 // (U1 / U2) / (U1 / U3) = U3 / U2
cannam@134 136 return UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit3, Unit2>(
cannam@134 137 unit1PerUnit2 / other.unit1PerUnit2);
cannam@134 138 }
cannam@134 139 template <typename OtherNumber, typename Unit3>
cannam@134 140 inline constexpr UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit1, Unit3>
cannam@134 141 operator/(UnitRatio<OtherNumber, Unit3, Unit2> other) const {
cannam@134 142 // (U1 / U2) / (U3 / U2) = U1 / U3
cannam@134 143 return UnitRatio<decltype(Number(1)*OtherNumber(1)), Unit1, Unit3>(
cannam@134 144 unit1PerUnit2 / other.unit1PerUnit2);
cannam@134 145 }
cannam@134 146
cannam@134 147 template <typename OtherNumber>
cannam@134 148 inline decltype(Number(1) / OtherNumber(1))
cannam@134 149 operator/(UnitRatio<OtherNumber, Unit1, Unit2> other) const {
cannam@134 150 return unit1PerUnit2 / other.unit1PerUnit2;
cannam@134 151 }
cannam@134 152
cannam@134 153 inline bool operator==(UnitRatio other) const { return unit1PerUnit2 == other.unit1PerUnit2; }
cannam@134 154 inline bool operator!=(UnitRatio other) const { return unit1PerUnit2 != other.unit1PerUnit2; }
cannam@134 155
cannam@134 156 private:
cannam@134 157 Number unit1PerUnit2;
cannam@134 158
cannam@134 159 template <typename OtherNumber, typename OtherUnit>
cannam@134 160 friend class Quantity;
cannam@134 161 template <typename OtherNumber, typename OtherUnit1, typename OtherUnit2>
cannam@134 162 friend class UnitRatio;
cannam@134 163
cannam@134 164 template <typename N1, typename N2, typename U1, typename U2>
cannam@134 165 friend inline constexpr UnitRatio<decltype(N1(1) * N2(1)), U1, U2>
cannam@134 166 operator*(N1, UnitRatio<N2, U1, U2>);
cannam@134 167 };
cannam@134 168
cannam@134 169 template <typename N1, typename N2, typename U1, typename U2>
cannam@134 170 inline constexpr UnitRatio<decltype(N1(1) * N2(1)), U1, U2>
cannam@134 171 operator*(N1 n, UnitRatio<N2, U1, U2> r) {
cannam@134 172 return UnitRatio<decltype(N1(1) * N2(1)), U1, U2>(n * r.unit1PerUnit2);
cannam@134 173 }
cannam@134 174
cannam@134 175 template <typename Number, typename Unit>
cannam@134 176 class Quantity {
cannam@134 177 // A type-safe numeric quantity, specified in terms of some unit. Two Quantities cannot be used
cannam@134 178 // in arithmetic unless they use the same unit. The `Unit` type parameter is only used to prevent
cannam@134 179 // accidental mixing of units; this type is never instantiated and can very well be incomplete.
cannam@134 180 // `Number` is the underlying primitive numeric type.
cannam@134 181 //
cannam@134 182 // Quantities support most basic arithmetic operators, intelligently handling units, and
cannam@134 183 // automatically casting the underlying type in the same way that the compiler would.
cannam@134 184 //
cannam@134 185 // To convert a primitive number to a Quantity, multiply it by unit<Quantity<N, U>>().
cannam@134 186 // To convert a Quantity to a primitive number, divide it by unit<Quantity<N, U>>().
cannam@134 187 // To convert a Quantity of one unit to another unit, multiply or divide by a UnitRatio.
cannam@134 188 //
cannam@134 189 // The Quantity class is not well-suited to hardcore physics as it does not allow multiplying
cannam@134 190 // one quantity by another. For example, multiplying meters by meters won't get you square
cannam@134 191 // meters; it will get you a compiler error. It would be interesting to see if template
cannam@134 192 // metaprogramming could properly deal with such things but this isn't needed for the present
cannam@134 193 // use case.
cannam@134 194 //
cannam@134 195 // Sample usage:
cannam@134 196 //
cannam@134 197 // class SecondsLabel;
cannam@134 198 // typedef Quantity<double, SecondsLabel> Seconds;
cannam@134 199 // constexpr Seconds SECONDS = unit<Seconds>();
cannam@134 200 //
cannam@134 201 // class MinutesLabel;
cannam@134 202 // typedef Quantity<double, MinutesLabel> Minutes;
cannam@134 203 // constexpr Minutes MINUTES = unit<Minutes>();
cannam@134 204 //
cannam@134 205 // constexpr UnitRatio<double, SecondsLabel, MinutesLabel> SECONDS_PER_MINUTE =
cannam@134 206 // 60 * SECONDS / MINUTES;
cannam@134 207 //
cannam@134 208 // void waitFor(Seconds seconds) {
cannam@134 209 // sleep(seconds / SECONDS);
cannam@134 210 // }
cannam@134 211 // void waitFor(Minutes minutes) {
cannam@134 212 // waitFor(minutes * SECONDS_PER_MINUTE);
cannam@134 213 // }
cannam@134 214 //
cannam@134 215 // void waitThreeMinutes() {
cannam@134 216 // waitFor(3 * MINUTES);
cannam@134 217 // }
cannam@134 218
cannam@134 219 static_assert(isIntegral<Number>(), "Underlying type for Quantity must be integer.");
cannam@134 220
cannam@134 221 public:
cannam@134 222 inline constexpr Quantity() {}
cannam@134 223
cannam@134 224 inline constexpr Quantity(MaxValue_): value(maxValue) {}
cannam@134 225 inline constexpr Quantity(MinValue_): value(minValue) {}
cannam@134 226 // Allow initialization from maxValue and minValue.
cannam@134 227 // TODO(msvc): decltype(maxValue) and decltype(minValue) deduce unknown-type for these function
cannam@134 228 // parameters, causing the compiler to complain of a duplicate constructor definition, so we
cannam@134 229 // specify MaxValue_ and MinValue_ types explicitly.
cannam@134 230
cannam@134 231 inline explicit constexpr Quantity(Number value): value(value) {}
cannam@134 232 // This constructor was intended to be private, but GCC complains about it being private in a
cannam@134 233 // bunch of places that don't appear to even call it, so I made it public. Oh well.
cannam@134 234
cannam@134 235 template <typename OtherNumber>
cannam@134 236 inline constexpr Quantity(const Quantity<OtherNumber, Unit>& other)
cannam@134 237 : value(other.value) {}
cannam@134 238
cannam@134 239 template <typename OtherNumber>
cannam@134 240 inline constexpr Quantity<decltype(Number(1) + OtherNumber(1)), Unit>
cannam@134 241 operator+(const Quantity<OtherNumber, Unit>& other) const {
cannam@134 242 return Quantity<decltype(Number(1) + OtherNumber(1)), Unit>(value + other.value);
cannam@134 243 }
cannam@134 244 template <typename OtherNumber>
cannam@134 245 inline constexpr Quantity<decltype(Number(1) - OtherNumber(1)), Unit>
cannam@134 246 operator-(const Quantity<OtherNumber, Unit>& other) const {
cannam@134 247 return Quantity<decltype(Number(1) - OtherNumber(1)), Unit>(value - other.value);
cannam@134 248 }
cannam@134 249 template <typename OtherNumber>
cannam@134 250 inline constexpr Quantity<decltype(Number(1) * OtherNumber(1)), Unit>
cannam@134 251 operator*(OtherNumber other) const {
cannam@134 252 static_assert(isIntegral<OtherNumber>(), "Multiplied Quantity by non-integer.");
cannam@134 253 return Quantity<decltype(Number(1) * other), Unit>(value * other);
cannam@134 254 }
cannam@134 255 template <typename OtherNumber>
cannam@134 256 inline constexpr Quantity<decltype(Number(1) / OtherNumber(1)), Unit>
cannam@134 257 operator/(OtherNumber other) const {
cannam@134 258 static_assert(isIntegral<OtherNumber>(), "Divided Quantity by non-integer.");
cannam@134 259 return Quantity<decltype(Number(1) / other), Unit>(value / other);
cannam@134 260 }
cannam@134 261 template <typename OtherNumber>
cannam@134 262 inline constexpr decltype(Number(1) / OtherNumber(1))
cannam@134 263 operator/(const Quantity<OtherNumber, Unit>& other) const {
cannam@134 264 return value / other.value;
cannam@134 265 }
cannam@134 266 template <typename OtherNumber>
cannam@134 267 inline constexpr decltype(Number(1) % OtherNumber(1))
cannam@134 268 operator%(const Quantity<OtherNumber, Unit>& other) const {
cannam@134 269 return value % other.value;
cannam@134 270 }
cannam@134 271
cannam@134 272 template <typename OtherNumber, typename OtherUnit>
cannam@134 273 inline constexpr Quantity<decltype(Number(1) * OtherNumber(1)), OtherUnit>
cannam@134 274 operator*(const UnitRatio<OtherNumber, OtherUnit, Unit>& ratio) const {
cannam@134 275 return Quantity<decltype(Number(1) * OtherNumber(1)), OtherUnit>(
cannam@134 276 value * ratio.unit1PerUnit2);
cannam@134 277 }
cannam@134 278 template <typename OtherNumber, typename OtherUnit>
cannam@134 279 inline constexpr Quantity<decltype(Number(1) / OtherNumber(1)), OtherUnit>
cannam@134 280 operator/(const UnitRatio<OtherNumber, Unit, OtherUnit>& ratio) const {
cannam@134 281 return Quantity<decltype(Number(1) / OtherNumber(1)), OtherUnit>(
cannam@134 282 value / ratio.unit1PerUnit2);
cannam@134 283 }
cannam@134 284 template <typename OtherNumber, typename OtherUnit>
cannam@134 285 inline constexpr Quantity<decltype(Number(1) % OtherNumber(1)), Unit>
cannam@134 286 operator%(const UnitRatio<OtherNumber, Unit, OtherUnit>& ratio) const {
cannam@134 287 return Quantity<decltype(Number(1) % OtherNumber(1)), Unit>(
cannam@134 288 value % ratio.unit1PerUnit2);
cannam@134 289 }
cannam@134 290 template <typename OtherNumber, typename OtherUnit>
cannam@134 291 inline constexpr UnitRatio<decltype(Number(1) / OtherNumber(1)), Unit, OtherUnit>
cannam@134 292 operator/(const Quantity<OtherNumber, OtherUnit>& other) const {
cannam@134 293 return UnitRatio<decltype(Number(1) / OtherNumber(1)), Unit, OtherUnit>(value / other.value);
cannam@134 294 }
cannam@134 295
cannam@134 296 template <typename OtherNumber>
cannam@134 297 inline constexpr bool operator==(const Quantity<OtherNumber, Unit>& other) const {
cannam@134 298 return value == other.value;
cannam@134 299 }
cannam@134 300 template <typename OtherNumber>
cannam@134 301 inline constexpr bool operator!=(const Quantity<OtherNumber, Unit>& other) const {
cannam@134 302 return value != other.value;
cannam@134 303 }
cannam@134 304 template <typename OtherNumber>
cannam@134 305 inline constexpr bool operator<=(const Quantity<OtherNumber, Unit>& other) const {
cannam@134 306 return value <= other.value;
cannam@134 307 }
cannam@134 308 template <typename OtherNumber>
cannam@134 309 inline constexpr bool operator>=(const Quantity<OtherNumber, Unit>& other) const {
cannam@134 310 return value >= other.value;
cannam@134 311 }
cannam@134 312 template <typename OtherNumber>
cannam@134 313 inline constexpr bool operator<(const Quantity<OtherNumber, Unit>& other) const {
cannam@134 314 return value < other.value;
cannam@134 315 }
cannam@134 316 template <typename OtherNumber>
cannam@134 317 inline constexpr bool operator>(const Quantity<OtherNumber, Unit>& other) const {
cannam@134 318 return value > other.value;
cannam@134 319 }
cannam@134 320
cannam@134 321 template <typename OtherNumber>
cannam@134 322 inline Quantity& operator+=(const Quantity<OtherNumber, Unit>& other) {
cannam@134 323 value += other.value;
cannam@134 324 return *this;
cannam@134 325 }
cannam@134 326 template <typename OtherNumber>
cannam@134 327 inline Quantity& operator-=(const Quantity<OtherNumber, Unit>& other) {
cannam@134 328 value -= other.value;
cannam@134 329 return *this;
cannam@134 330 }
cannam@134 331 template <typename OtherNumber>
cannam@134 332 inline Quantity& operator*=(OtherNumber other) {
cannam@134 333 value *= other;
cannam@134 334 return *this;
cannam@134 335 }
cannam@134 336 template <typename OtherNumber>
cannam@134 337 inline Quantity& operator/=(OtherNumber other) {
cannam@134 338 value /= other.value;
cannam@134 339 return *this;
cannam@134 340 }
cannam@134 341
cannam@134 342 private:
cannam@134 343 Number value;
cannam@134 344
cannam@134 345 template <typename OtherNumber, typename OtherUnit>
cannam@134 346 friend class Quantity;
cannam@134 347
cannam@134 348 template <typename Number1, typename Number2, typename Unit2>
cannam@134 349 friend inline constexpr auto operator*(Number1 a, Quantity<Number2, Unit2> b)
cannam@134 350 -> Quantity<decltype(Number1(1) * Number2(1)), Unit2>;
cannam@134 351
cannam@134 352 template <typename T>
cannam@134 353 friend inline constexpr T unit();
cannam@134 354 };
cannam@134 355
cannam@134 356 template <typename T>
cannam@134 357 inline constexpr T unit() { return T(1); }
cannam@134 358 // unit<Quantity<T, U>>() returns a Quantity of value 1. It also, intentionally, works on basic
cannam@134 359 // numeric types.
cannam@134 360
cannam@134 361 template <typename Number1, typename Number2, typename Unit>
cannam@134 362 inline constexpr auto operator*(Number1 a, Quantity<Number2, Unit> b)
cannam@134 363 -> Quantity<decltype(Number1(1) * Number2(1)), Unit> {
cannam@134 364 return Quantity<decltype(Number1(1) * Number2(1)), Unit>(a * b.value);
cannam@134 365 }
cannam@134 366
cannam@134 367 template <typename Number1, typename Number2, typename Unit, typename Unit2>
cannam@134 368 inline constexpr auto operator*(UnitRatio<Number1, Unit2, Unit> ratio,
cannam@134 369 Quantity<Number2, Unit> measure)
cannam@134 370 -> decltype(measure * ratio) {
cannam@134 371 return measure * ratio;
cannam@134 372 }
cannam@134 373
cannam@134 374 // =======================================================================================
cannam@134 375 // Absolute measures
cannam@134 376
cannam@134 377 template <typename T, typename Label>
cannam@134 378 class Absolute {
cannam@134 379 // Wraps some other value -- typically a Quantity -- but represents a value measured based on
cannam@134 380 // some absolute origin. For example, if `Duration` is a type representing a time duration,
cannam@134 381 // Absolute<Duration, UnixEpoch> might be a calendar date.
cannam@134 382 //
cannam@134 383 // Since Absolute represents measurements relative to some arbitrary origin, the only sensible
cannam@134 384 // arithmetic to perform on them is addition and subtraction.
cannam@134 385
cannam@134 386 // TODO(someday): Do the same automatic expansion of integer width that Quantity does? Doesn't
cannam@134 387 // matter for our time use case, where we always use 64-bit anyway. Note that fixing this
cannam@134 388 // would implicitly allow things like multiplying an Absolute by a UnitRatio to change its
cannam@134 389 // units, which is actually totally logical and kind of neat.
cannam@134 390
cannam@134 391 public:
cannam@134 392 inline constexpr Absolute operator+(const T& other) const { return Absolute(value + other); }
cannam@134 393 inline constexpr Absolute operator-(const T& other) const { return Absolute(value - other); }
cannam@134 394 inline constexpr T operator-(const Absolute& other) const { return value - other.value; }
cannam@134 395
cannam@134 396 inline Absolute& operator+=(const T& other) { value += other; return *this; }
cannam@134 397 inline Absolute& operator-=(const T& other) { value -= other; return *this; }
cannam@134 398
cannam@134 399 inline constexpr bool operator==(const Absolute& other) const { return value == other.value; }
cannam@134 400 inline constexpr bool operator!=(const Absolute& other) const { return value != other.value; }
cannam@134 401 inline constexpr bool operator<=(const Absolute& other) const { return value <= other.value; }
cannam@134 402 inline constexpr bool operator>=(const Absolute& other) const { return value >= other.value; }
cannam@134 403 inline constexpr bool operator< (const Absolute& other) const { return value < other.value; }
cannam@134 404 inline constexpr bool operator> (const Absolute& other) const { return value > other.value; }
cannam@134 405
cannam@134 406 private:
cannam@134 407 T value;
cannam@134 408
cannam@134 409 explicit constexpr Absolute(T value): value(value) {}
cannam@134 410
cannam@134 411 template <typename U>
cannam@134 412 friend inline constexpr U origin();
cannam@134 413 };
cannam@134 414
cannam@134 415 template <typename T, typename Label>
cannam@134 416 inline constexpr Absolute<T, Label> operator+(const T& a, const Absolute<T, Label>& b) {
cannam@134 417 return b + a;
cannam@134 418 }
cannam@134 419
cannam@134 420 template <typename T> struct UnitOf_ { typedef T Type; };
cannam@134 421 template <typename T, typename Label> struct UnitOf_<Absolute<T, Label>> { typedef T Type; };
cannam@134 422 template <typename T>
cannam@134 423 using UnitOf = typename UnitOf_<T>::Type;
cannam@134 424 // UnitOf<Absolute<T, U>> is T. UnitOf<AnythingElse> is AnythingElse.
cannam@134 425
cannam@134 426 template <typename T>
cannam@134 427 inline constexpr T origin() { return T(0 * unit<UnitOf<T>>()); }
cannam@134 428 // origin<Absolute<T, U>>() returns an Absolute of value 0. It also, intentionally, works on basic
cannam@134 429 // numeric types.
cannam@134 430
cannam@134 431 } // namespace kj
cannam@134 432
cannam@134 433 #endif // KJ_UNITS_H_