Go to the documentation of this file.
9 #ifndef EAGINE_TAGGED_QUANTITY_HPP
10 #define EAGINE_TAGGED_QUANTITY_HPP
17 #include <type_traits>
21 EAGINE_DIAG_OFF(
double-promotion)
26 template <
typename T,
typename U>
29 template <
typename U,
typename T>
30 static constexpr
auto make_tagged_quantity(
const T& value)
35 template <
typename T,
typename U>
55 typename = std::enable_if_t<
56 std::is_convertible_v<X, T> && units::is_convertible_v<UX, U>>>
58 : _v(T(units::value_conv<UX, U>()(tq._v))) {}
63 typename = std::enable_if_t<units::is_convertible_v<U, UX>>>
64 constexpr
auto to() const noexcept {
65 return make_tagged_quantity<UX>(units::value_conv<U, UX>()(_v));
69 constexpr
auto value() const noexcept -> T {
74 static constexpr
auto unit() noexcept -> U {
81 typename = std::enable_if_t<std::is_convertible_v<T, X>>>
82 explicit constexpr
operator X() const noexcept {
90 typename = std::enable_if_t<
91 std::is_convertible_v<X, T> && units::is_convertible_v<UX, U>>>
93 _v += T(units::value_conv<UX, U>()(q._v));
101 typename = std::enable_if_t<
102 std::is_convertible_v<X, T> && units::is_convertible_v<UX, U>>>
104 _v -= T(units::value_conv<UX, U>()(q._v));
109 static_assert(std::is_arithmetic_v<T>);
112 template <
typename,
typename>
113 friend class tagged_quantity;
117 template <
typename T>
118 struct is_tagged_quantity : std::false_type {};
120 template <
typename T>
121 using is_tagged_quantity_t =
typename is_tagged_quantity<T>::type;
123 template <
typename T>
124 constexpr
bool is_tagged_quantity_v = is_tagged_quantity<T>::value;
126 template <
typename T,
typename U>
127 struct is_tagged_quantity<tagged_quantity<T, U>> : std::true_type {};
130 template <
typename Qty,
typename Unit>
131 struct is_convertible_quantity : std::false_type {};
133 template <
typename Q,
typename U>
134 using is_convertible_quantity_t =
typename is_convertible_quantity<Q, U>::type;
136 template <
typename Q,
typename U>
137 constexpr
bool is_convertible_quantity_v = is_convertible_quantity<Q, U>::value;
139 template <
typename T,
typename QU,
typename U>
140 struct is_convertible_quantity<tagged_quantity<T, QU>, U>
141 : units::is_convertible<QU, U> {};
144 template <
typename U,
typename T>
145 static constexpr
auto make_tagged_quantity(
const T& value)
146 -> tagged_quantity<T, U> {
147 return tagged_quantity<T, U>{value};
153 typename = std::enable_if_t<
154 !is_tagged_quantity_v<T> && !units::is_unit_v<T> && units::is_unit_v<U>>>
155 static constexpr
auto operator*(
const T& v, U) {
156 return make_tagged_quantity<U>(v);
159 template <
typename UX,
typename T,
typename U>
160 static inline auto convert_to(
const tagged_quantity<T, U>& q) {
161 return q.template to<UX>();
164 template <
typename T,
typename U>
165 static inline auto value(
const tagged_quantity<T, U>& q) {
169 template <
typename T1,
typename U1,
typename T2,
typename U2>
170 struct equal_cmp<tagged_quantity<T1, U1>, tagged_quantity<T2, U2>> {
172 static_assert(units::is_convertible_v<U2, U1>);
174 static constexpr
auto check(
175 const tagged_quantity<T1, U1>& l,
176 const tagged_quantity<T2, U2>& r) noexcept ->
bool {
177 return are_equal(value(l), units::value_conv<U2, U1>()(value(r)));
184 template <
typename T1,
typename U1,
typename T2,
typename U2>
187 -> std::enable_if_t<units::is_convertible_v<U2, U1>,
bool> {
188 return value(a) == units::value_conv<U2, U1>()(value(b));
194 template <
typename T1,
typename U1,
typename T2,
typename U2>
197 -> std::enable_if_t<units::is_convertible_v<U2, U1>,
bool> {
198 return value(a) != units::value_conv<U2, U1>()(value(b));
204 template <
typename T1,
typename U1,
typename T2,
typename U2>
207 -> std::enable_if_t<units::is_convertible_v<U2, U1>,
bool> {
208 return value(a) < units::value_conv<U2, U1>()(value(b));
214 template <
typename T1,
typename U1,
typename T2,
typename U2>
217 -> std::enable_if_t<units::is_convertible_v<U2, U1>,
bool> {
218 return value(a) <= units::value_conv<U2, U1>()(value(b));
224 template <
typename T1,
typename U1,
typename T2,
typename U2>
227 -> std::enable_if_t<units::is_convertible_v<U2, U1>,
bool> {
228 return value(a) > units::value_conv<U2, U1>()(value(b));
234 template <
typename T1,
typename U1,
typename T2,
typename U2>
237 -> std::enable_if_t<units::is_convertible_v<U2, U1>,
bool> {
238 return value(a) >= units::value_conv<U2, U1>()(value(b));
244 template <
typename T,
typename U>
252 template <
typename T,
typename U>
254 return make_tagged_quantity<U>(-value(a));
260 template <
typename T1,
typename U1,
typename T2,
typename U2>
263 using UR = units::add_result_t<U1, U2>;
264 return make_tagged_quantity<UR>(
265 units::value_conv<U1, UR>()(value(a)) +
266 units::value_conv<U2, UR>()(value(b)));
272 template <
typename T1,
typename U1,
typename T2,
typename U2>
275 using UR = units::sub_result_t<U1, U2>;
276 return make_tagged_quantity<UR>(
277 units::value_conv<U1, UR>()(value(a)) -
278 units::value_conv<U2, UR>()(value(b)));
284 template <
typename T1,
typename U1,
typename T2,
typename U2>
287 using UO1 = units::mul_l_operand_t<U1, U2>;
288 using UO2 = units::mul_r_operand_t<U1, U2>;
289 using UR = units::mul_result_t<U1, U2>;
290 return make_tagged_quantity<UR>(
291 units::value_conv<U1, UO1>()(value(a)) *
292 units::value_conv<U2, UO2>()(value(b)));
302 typename = std::enable_if_t<!units::is_unit_v<T2> && !is_tagged_quantity_v<T2>>>
304 return make_tagged_quantity<U>(value(a) * c);
310 template <
typename T1,
typename T2,
typename U>
312 return make_tagged_quantity<U>(c * value(a));
322 typename = std::enable_if_t<units::is_unit_v<U2>>>
324 return a * make_tagged_quantity<U2>(1);
330 template <
typename T1,
typename U1,
typename T2,
typename U2>
333 using UO1 = units::div_l_operand_t<U1, U2>;
334 using UO2 = units::div_r_operand_t<U1, U2>;
335 using UR = units::div_result_t<U1, U2>;
336 return make_tagged_quantity<UR>(
337 units::value_conv<U1, UO1>()(value(a)) /
338 units::value_conv<U2, UO2>()(value(b)));
348 typename = std::enable_if_t<!units::is_unit_v<T2>>>
350 return make_tagged_quantity<U>((1.F * value(a)) / c);
360 typename = std::enable_if_t<units::is_unit_v<U2>>>
362 return a / make_tagged_quantity<U2>(1);
371 #endif // EAGINE_TAGGED_QUANTITY_HPP
constexpr auto operator/(const tagged_quantity< T1, U1 > &a, U2)
Constant division operator.
Definition: tagged_quantity.hpp:361
constexpr auto operator/(const tagged_quantity< T1, U > &a, const T2 &c)
Division by constant operator.
Definition: tagged_quantity.hpp:349
U unit_type
Alias for the unit type.
Definition: tagged_quantity.hpp:39
constexpr tagged_quantity(const tagged_quantity< X, UX > &tq) noexcept
Converting constructor from another tagged quantity.
Definition: tagged_quantity.hpp:57
constexpr auto operator>=(const tagged_quantity< T1, U1 > &a, const tagged_quantity< T2, U2 > &b) -> std::enable_if_t< units::is_convertible_v< U2, U1 >, bool >
Greater-equal comparison.
Definition: tagged_quantity.hpp:236
Common code is placed in this namespace.
Definition: eagine.hpp:21
static constexpr auto operator<=(const valid_if< T, P1 > &v1, const valid_if< T, P2 > &v2) noexcept -> tribool
Less-equal comparison of two conditionally valid values.
Definition: decl.hpp:202
constexpr auto operator-(const tagged_quantity< T, U > &a)
Unary negation operator.
Definition: tagged_quantity.hpp:253
constexpr auto operator+(const tagged_quantity< T, U > &a)
Unary plus operator.
Definition: tagged_quantity.hpp:245
constexpr auto operator*(const tagged_quantity< T1, U > &a, const T2 &c)
Multiplication by constant operator.
Definition: tagged_quantity.hpp:303
constexpr auto operator==(const tagged_quantity< T1, U1 > &a, const tagged_quantity< T2, U2 > &b) -> std::enable_if_t< units::is_convertible_v< U2, U1 >, bool >
Equality comparison.
Definition: tagged_quantity.hpp:186
constexpr auto operator*(const tagged_quantity< T1, U1 > &a, U2)
Multiplication by unit operator.
Definition: tagged_quantity.hpp:323
auto operator-=(const tagged_quantity< X, UX > &q) noexcept -> auto &
Subtraction of another tagged quantity.
Definition: tagged_quantity.hpp:103
static constexpr auto unit() noexcept -> U
Returns the unit.
Definition: tagged_quantity.hpp:74
auto operator+=(const tagged_quantity< X, UX > &q) noexcept -> auto &
Addition of another tagged quantity.
Definition: tagged_quantity.hpp:92
constexpr auto operator/(const tagged_quantity< T1, U1 > &a, const tagged_quantity< T2, U2 > &b)
Division operator.
Definition: tagged_quantity.hpp:332
constexpr auto to() const noexcept
Conversion to a quantity in another unit type.
Definition: tagged_quantity.hpp:64
constexpr auto operator+(const tagged_quantity< T1, U1 > &a, const tagged_quantity< T2, U2 > &b)
Addition operator.
Definition: tagged_quantity.hpp:262
constexpr auto value() const noexcept -> T
Returns the value.
Definition: tagged_quantity.hpp:69
constexpr auto operator>(const tagged_quantity< T1, U1 > &a, const tagged_quantity< T2, U2 > &b) -> std::enable_if_t< units::is_convertible_v< U2, U1 >, bool >
Greater-than comparison.
Definition: tagged_quantity.hpp:226
T value_type
Alias for the value type.
Definition: tagged_quantity.hpp:42
constexpr auto operator*(const T1 &c, const tagged_quantity< T2, U > &a)
Multiplication by constant operator.
Definition: tagged_quantity.hpp:311
constexpr auto operator-(const tagged_quantity< T1, U1 > &a, const tagged_quantity< T2, U2 > &b)
Subtraction operator.
Definition: tagged_quantity.hpp:274
constexpr auto operator*(const tagged_quantity< T1, U1 > &a, const tagged_quantity< T2, U2 > &b)
Multiplication operator.
Definition: tagged_quantity.hpp:286
static constexpr auto operator<(const valid_if< T, P1 > &v1, const valid_if< T, P2 > &v2) noexcept -> tribool
Less-than comparison of two conditionally valid values.
Definition: decl.hpp:180
constexpr auto operator!=(const tagged_quantity< T1, U1 > &a, const tagged_quantity< T2, U2 > &b) -> std::enable_if_t< units::is_convertible_v< U2, U1 >, bool >
Nonequality comparison.
Definition: tagged_quantity.hpp:196
Value of type T with a specified unit or tag type U.
Definition: tagged_quantity.hpp:27
constexpr tagged_quantity(T v) noexcept
Explicit constructor initializing the value.
Definition: tagged_quantity.hpp:48