14 #ifdef SI_DISABLE_IMPLICIT_RATIO_CONVERSION
15 #define SI_ENABLE_IMPLICIT_RATIO_CONVERSION false
17 #define SI_ENABLE_IMPLICIT_RATIO_CONVERSION true
25 #include <type_traits>
30 template <
typename _unit_lhs,
typename _unit_rhs>
struct unit_with_common_ratio;
49 template <
char _symbol,
typename _exponent,
typename _type,
50 typename _ratio = std::ratio<1>>
52 static_assert(std::is_arithmetic_v<_type>,
"Type is an arithmetic value");
53 static_assert(detail::is_ratio_v<_exponent>,
"_exponent is a ratio type");
54 static_assert(detail::is_ratio_v<_ratio>,
"_ratio is a std::ratio");
58 using symbol = std::integral_constant<char, _symbol>;
61 explicit constexpr
unit_t(_type v) : value_{v} {}
67 template <
typename _type_rhs>
69 : value_(rhs.
value()) {
70 static_assert(std::is_convertible<_type_rhs, _type>::value,
71 "Internal representation is convertible");
76 template <
typename _rhs_type,
typename _rhs_ratio>
80 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
83 std::ratio_equal_v<ratio, _rhs_ratio>,
84 "Implicit ratio conversion disabled, convert before assigning");
87 template <
typename _rhs_ratio>
92 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
95 std::ratio_equal_v<ratio, _rhs_ratio>,
96 "Implicit ratio conversion disabled, convert before assigning");
100 constexpr _type
value()
const {
return value_; }
104 template <
typename _unit_rhs> constexpr _unit_rhs
as()
const {
105 static_assert(is_unit_t_v<_unit_rhs>,
"only supported for SI::unit_t");
106 static_assert(std::ratio_equal_v<typename _unit_rhs::exponent, _exponent>,
107 "Exponents must match");
108 static_assert(_unit_rhs::symbol::value == _symbol,
109 "target unit must be of the same type must match");
111 return unit_cast<_unit_rhs>(*
this);
116 template <
template <
typename _type_rhs>
typename _unit_rhs>
117 constexpr _unit_rhs<_type>
as()
const {
119 "only supported for SI::unit_t");
121 std::ratio_equal_v<
typename _unit_rhs<_type>::exponent, _exponent>,
122 "Exponents must match");
123 static_assert(_unit_rhs<_type>::symbol::value == _symbol,
124 "target unit must be of the same type must match");
126 return unit_cast<_unit_rhs<_type>>(*this);
141 std::enable_if_t<!std::ratio_equal_v<_rhs_ratio, _ratio>> * =
nullptr>
145 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
148 std::ratio_equal_v<ratio, _rhs_ratio>,
149 "Implicit ratio conversion disabled, convert before assigning");
151 *
this = unit_cast<unit_t<_symbol, _exponent, _type, _ratio>>(rhs);
158 std::enable_if_t<!std::ratio_equal_v<_rhs_ratio, _ratio>> * =
nullptr>
162 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
165 std::ratio_equal_v<ratio, _rhs_ratio>,
166 "Implicit ratio conversion disabled, convert before assigning");
175 template <
typename _rhs_type,
typename _rhs_ratio>
181 std::ratio_equal_v<ratio, _rhs_ratio>,
182 "Implicit ratio conversion disabled, convert before comparing");
184 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
185 static_assert(std::is_integral_v<_type> || std::is_floating_point_v<_type>,
186 "Is integral or floating point");
188 typename std::remove_reference<decltype(rhs)>::type,
189 typename std::remove_reference<decltype(*
this)>::type>::type;
191 if constexpr (std::is_integral_v<_type>) {
193 return unit_cast<gcd_unit>(rhs).value() ==
194 unit_cast<gcd_unit>(*this).value();
197 unit_cast<gcd_unit>(*this).value());
202 template <
typename _rhs_type,
typename _rhs_ratio>
205 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
206 return !(*
this == rhs);
209 template <
typename _rhs_type,
typename _rhs_ratio>
212 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
215 std::ratio_equal_v<ratio, _rhs_ratio>,
216 "Implicit ratio conversion disabled, convert before comparing");
219 typename std::remove_reference<decltype(rhs)>::type,
220 typename std::remove_reference<decltype(*
this)>::type>::type;
221 return unit_cast<gcd_unit>(*this).value() <
222 unit_cast<gcd_unit>(rhs).value();
225 template <
typename _rhs_type,
typename _rhs_ratio>
228 return !(*
this > rhs);
231 template <
typename _rhs_type,
typename _rhs_ratio>
234 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
237 std::ratio_equal_v<ratio, _rhs_ratio>,
238 "Implicit ratio conversion disabled, convert before comparing");
241 typename std::remove_reference<decltype(rhs)>::type,
242 typename std::remove_reference<decltype(*
this)>::type>::type;
244 return unit_cast<gcd_unit>(*this).value() >
245 unit_cast<gcd_unit>(rhs).value();
248 template <
typename _rhs_type,
typename _rhs_ratio>
251 return !(*
this < rhs);
258 template <
typename _rhs_exponent,
typename _rhs_type>
262 static_assert(detail::is_ratio_v<_rhs_exponent>,
263 "rhs exponent is a ratio type");
265 std::ratio_multiply<ratio, _ratio>>{
value() * rhs.
value()};
272 template <
typename _rhs_exponent,
typename _rhs_ratio,
typename _rhs_type>
275 static_assert(detail::is_ratio_v<_rhs_exponent>,
276 "rhs exponent is a ratio type");
277 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
281 std::ratio_equal_v<ratio, _rhs_ratio>,
282 "Implicit ratio conversion disabled, convert before comparing");
285 std::ratio_multiply<ratio, _rhs_ratio>>{value_ * rhs.
value()};
299 template <
typename _rhs_exponent,
typename _rhs_type,
300 std::enable_if_t<std::ratio_not_equal_v<_rhs_exponent, _exponent>>
304 static_assert(detail::is_ratio_v<_rhs_exponent>,
305 "rhs exponent is a ratio type");
306 using rhs_t =
typename std::remove_reference<decltype(rhs)>::type;
309 std::ratio_subtract<_exponent, typename rhs_t::exponent>,
310 _type, std::ratio_divide<ratio, _ratio>>{value_ /
317 template <
typename _rhs_exponent,
typename _rhs_type,
typename _rhs_ratio,
318 std::enable_if_t<std::ratio_not_equal_v<_rhs_exponent, _exponent>>
322 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
323 static_assert(detail::is_ratio_v<_rhs_exponent>,
324 "rhs exponent is a ratio type");
327 std::ratio_equal_v<ratio, _rhs_ratio>,
328 "Implicit ratio conversion disabled, convert before dividing");
331 std::ratio_divide<ratio, _rhs_ratio>>{value_ / rhs.
value()};
335 template <
typename _rhs_type>
344 typename _rhs_exponent,
typename _rhs_type,
typename _rhs_ratio,
345 std::enable_if_t<std::ratio_equal_v<_rhs_exponent, exponent>> * =
nullptr>
349 std::ratio_equal_v<_rhs_ratio, _ratio>,
350 "Implicit ratio conversion disabled, convert to same ratio "
353 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
355 static_assert(detail::is_ratio_v<_rhs_exponent>,
356 "rhs exponent is a ratio type");
359 typename std::remove_reference<decltype(*
this)>::type,
360 typename std::remove_reference<decltype(rhs)>::type>::type;
362 return unit_cast<gcd_unit>(*
this) / unit_cast<gcd_unit>(rhs);
372 template <
typename _rhs_type,
typename _rhs_ratio>
376 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
379 std::ratio_equal_v<ratio, _rhs_ratio>,
380 "Implicit ratio conversion disabled, convert before adding values");
384 unit_cast<unit_t<_symbol, _exponent, _type, _ratio>>(rhs).
value()};
389 value_ += rhs.
value();
395 typename _rhs_type,
typename _rhs_ratio,
396 std::enable_if_t<!std::ratio_equal_v<_rhs_ratio, _ratio>> * =
nullptr>
400 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
403 std::ratio_equal_v<ratio, _rhs_ratio>,
404 "Implicit ratio conversion disabled, convert before adding values");
406 value_ += unit_cast<unit_t<_symbol, _exponent, _type, _ratio>>(rhs).
value();
412 template <
typename _rhs_type,
typename _rhs_ratio>
416 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
419 std::ratio_equal_v<ratio, _rhs_ratio>,
420 "Implicit ratio conversion disabled, convert before subtracting");
424 -unit_cast<unit_t<_symbol, _exponent, _type, _ratio>>(rhs).
value()};
429 value_ -= rhs.
value();
434 template <
typename _rhs_type,
typename _rhs_ratio,
435 std::enable_if<!std::ratio_equal_v<_rhs_ratio, _ratio>> * =
nullptr>
439 static_assert(detail::is_ratio_v<_rhs_ratio>,
"_rhs_ratio is a std::ratio");
442 std::ratio_equal_v<ratio, _rhs_ratio>,
443 "Implicit ratio conversion disabled, convert before adding values");
445 value_ -= unit_cast<unit_t<_symbol, _exponent, _type, _ratio>>(rhs).
value();
487 template <
typename _type,
char _symbol,
typename _exponent,
typename _rhs_type,
489 std::enable_if_t<std::is_integral_v<_type>> * =
nullptr>
494 std::ratio_equal<std::ratio<1>, _ratio>::value,
495 "Implicit ratio conversion disabled, convert to ratio<1> "
497 static_assert(detail::is_ratio_v<_exponent>,
"Exponent is a ratio type");
498 return unit_t<_symbol, std::ratio_multiply<std::ratio<-1>, _exponent>, _type,
499 _ratio>{lhs / rhs.
value()};
506 template <
typename _type,
char _symbol,
typename _exponent,
typename _rhs_type,
508 std::enable_if_t<std::is_floating_point_v<_type>> * =
nullptr>
511 const unit_t<_symbol, _exponent, _rhs_type, _ratio> &rhs) {
513 std::ratio_equal_v<_ratio, std::ratio<1>>,
514 "Implicit ratio conversion disabled, convert to ratio<1> "
516 static_assert(detail::is_ratio_v<_exponent>,
"Exponent is a ratio type");
517 return unit_t<_symbol, std::ratio_multiply<std::ratio<-1>, _exponent>, _type,
518 _ratio>{lhs / rhs.value()};
Namespace containing implementation details for SI.
Definition: acceleration.h:34
constexpr auto unit_cast(const _rhs_T &rhs)
function to cast between two units of the same type
Definition: unit_cast.h:22
constexpr bool is_unit_t_v
Definition: detail.h:65
constexpr bool eps_equals(const T &lhs, const T &rhs)
Definition: eps_equal.h:22
constexpr auto operator/(const _type &lhs, const unit_t< _symbol, _exponent, _rhs_type, _ratio > &rhs)
Definition: unit.h:491
base template class for holding values of type _type to be multiplied with a ratio _ratio
Definition: unit.h:51
constexpr unit_t & operator-=(const unit_t &rhs)
Subtract-assign value of the same unit.
Definition: unit.h:428
constexpr bool operator>(const unit_t< _symbol, _exponent, _rhs_type, _rhs_ratio > &rhs) const
Definition: unit.h:232
_ratio ratio
Definition: unit.h:55
constexpr unit_t()=default
constexpr unit_t operator*(const _type f) const
multiply with a non-unit scalar
Definition: unit.h:255
constexpr unit_t & operator+=(const unit_t &rhs)
add-assign value of the same unit
Definition: unit.h:388
constexpr bool operator>=(const unit_t< _symbol, _exponent, _rhs_type, _rhs_ratio > &rhs) const
Definition: unit.h:249
void setValue(_type v)
Definition: unit.h:130
constexpr auto operator/(const unit_t< _symbol, _rhs_exponent, _rhs_type, _ratio > &rhs) const
Definition: unit.h:302
constexpr unit_t & operator-=(const unit_t< _symbol, _exponent, _type, _rhs_ratio > &rhs)
subtract value of the same type but possibly different ratio
Definition: unit.h:437
unit_t & operator--()
decrement by prefix –
Definition: unit.h:467
constexpr unit_t & operator=(unit_t &&rhs)=default
Move assignment for same ratio.
constexpr bool operator<=(const unit_t< _symbol, _exponent, _rhs_type, _rhs_ratio > &rhs) const
Definition: unit.h:226
unit_t operator++(int)
increment by postfix ++
Definition: unit.h:459
constexpr unit_t & operator=(const unit_t< _symbol, _exponent, _type, _rhs_ratio > &rhs)
Assignment of same unit but different ratio.
Definition: unit.h:143
constexpr _type operator/(const unit_t< _symbol, _exponent, _rhs_type, _ratio > &rhs)
divide whit same unit result is a scalar
Definition: unit.h:337
constexpr unit_t & operator=(const unit_t &rhs)=default
Assignment for same ratio.
_type internal_type
Definition: unit.h:56
constexpr _type operator/(const unit_t< _symbol, _rhs_exponent, _rhs_type, _rhs_ratio > &rhs) const
Definition: unit.h:346
constexpr unit_t(const unit_t< _symbol, _exponent, _type_rhs, _ratio > &rhs)
construct from other unit with implicitly convertible type
Definition: unit.h:68
constexpr auto operator*(const unit_t< _symbol, _rhs_exponent, _rhs_type, _rhs_ratio > &rhs) const
Definition: unit.h:273
constexpr unit_t(unit_t &&)=default
constexpr unit_t & operator/=(const _type scalar)
divide with a non-unit scalar
Definition: unit.h:366
_exponent exponent
Definition: unit.h:57
constexpr unit_t operator-(const unit_t< _symbol, _exponent, _rhs_type, _rhs_ratio > &rhs) const
subtracts two values, returning type is type of lhs
Definition: unit.h:413
constexpr bool operator<(const unit_t< _symbol, _exponent, _rhs_type, _rhs_ratio > &rhs) const
Definition: unit.h:210
constexpr unit_t operator+(const unit_t< _symbol, _exponent, _rhs_type, _rhs_ratio > &rhs) const
adds two values, returning type is type of lhs
Definition: unit.h:373
constexpr unit_t(const unit_t &)=default
constexpr unit_t operator-() const
negate operation
Definition: unit.h:451
unit_t & operator++()
increment by prefix ++
Definition: unit.h:454
constexpr bool operator!=(const unit_t< _symbol, _exponent, _rhs_type, _rhs_ratio > &rhs) const
compares two values, considers different ratios.
Definition: unit.h:203
unit_t operator--(int)
decrement by postfix –
Definition: unit.h:473
constexpr bool operator==(const unit_t< _symbol, _exponent, _rhs_type, _rhs_ratio > &rhs) const
Definition: unit.h:176
constexpr unit_t & operator*=(const _type scalar)
multiply with a non-unit scalar
Definition: unit.h:289
constexpr auto operator/(const unit_t< _symbol, _rhs_exponent, _rhs_type, _rhs_ratio > &rhs) const
Definition: unit.h:320
constexpr _unit_rhs as() const
Definition: unit.h:104
constexpr unit_t operator/(const _type f) const
divide by a non-unit scalar
Definition: unit.h:295
std::integral_constant< char, _symbol > symbol
Definition: unit.h:58
constexpr unit_t(_type v)
Construct with value v.
Definition: unit.h:61
constexpr unit_t(unit_t< _symbol, _exponent, _type, _rhs_ratio > &&rhs)
Definition: unit.h:88
constexpr _type value() const
returns the stored value as raw type
Definition: unit.h:100
constexpr unit_t & operator=(unit_t< _symbol, _exponent, _type, _rhs_ratio > &&rhs)
Move assignment of same unit but different ratio.
Definition: unit.h:160
constexpr unit_t & operator+=(const unit_t< _symbol, _exponent, _rhs_type, _rhs_ratio > &rhs)
add value of the same type but possibly different ratio
Definition: unit.h:398
constexpr _unit_rhs< _type > as() const
Definition: unit.h:117
constexpr unit_t(const unit_t< _symbol, _exponent, _rhs_type, _rhs_ratio > &rhs)
Definition: unit.h:77
constexpr auto operator*(const unit_t< _symbol, _rhs_exponent, _rhs_type, _ratio > &rhs) const
multiply with an unit of the same ratio
Definition: unit.h:259
Definition: unit_cast.h:49
#define SI_ENABLE_IMPLICIT_RATIO_CONVERSION
Definition: unit.h:17