mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-04 20:54:28 +02:00
quantity refactored and quantity_test enabled
This commit is contained in:
@@ -24,7 +24,6 @@
|
||||
|
||||
#include <units/bits/fixed_string.h>
|
||||
#include <units/bits/unit_concept.h>
|
||||
#include <units/unit.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace units {
|
||||
@@ -46,7 +45,7 @@ namespace units {
|
||||
*/
|
||||
template<basic_fixed_string Name, Unit U>
|
||||
struct base_dimension {
|
||||
using base_type = base_dimension;
|
||||
using base_type_workaround = base_dimension; // TODO Replace with is_derived_from_instantiation when fixed
|
||||
static constexpr auto name = Name;
|
||||
using coherent_unit = U;
|
||||
};
|
||||
@@ -63,7 +62,7 @@ inline constexpr bool is_base_dimension<base_dimension<Name, Params...>> = true;
|
||||
} // namespace detail
|
||||
|
||||
template<typename T>
|
||||
concept BaseDimension = detail::is_base_dimension<typename T::base_type>;
|
||||
concept BaseDimension = detail::is_base_dimension<typename T::base_type_workaround>;
|
||||
|
||||
// base_dimension_less
|
||||
// TODO Remove the below when https://bugs.llvm.org/show_bug.cgi?id=32208 is fixed
|
||||
|
@@ -1,115 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
namespace units {
|
||||
|
||||
// treat_as_floating_point
|
||||
|
||||
template<typename Rep> // TODO Conceptify that
|
||||
inline constexpr bool treat_as_floating_point = std::is_floating_point_v<Rep>;
|
||||
|
||||
// isnan
|
||||
namespace isnan_impl {
|
||||
|
||||
// non-ADL lookup block
|
||||
void isnan(); // undefined
|
||||
|
||||
template<typename>
|
||||
inline constexpr bool has_customization = false;
|
||||
|
||||
template<typename T>
|
||||
requires requires(const T& t) {
|
||||
{ isnan(t) } -> bool;
|
||||
}
|
||||
inline constexpr bool has_customization<T> = true;
|
||||
|
||||
struct fn {
|
||||
template<typename T>
|
||||
constexpr bool operator()(const T&) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires treat_as_floating_point<T>
|
||||
constexpr bool operator()(const T& value) const
|
||||
{
|
||||
return std::isnan(value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires treat_as_floating_point<T> && has_customization<T>
|
||||
constexpr bool operator()(const T& value) const
|
||||
{
|
||||
return isnan(value); // uses ADL
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline constexpr isnan_impl::fn isnan{};
|
||||
|
||||
// isfinite
|
||||
namespace isfinite_impl {
|
||||
|
||||
// non-ADL lookup block
|
||||
void isfinite(); // undefined
|
||||
|
||||
template<typename>
|
||||
inline constexpr bool has_customization = false;
|
||||
|
||||
template<typename T>
|
||||
requires requires(const T& t) {
|
||||
{ isfinite(t) } -> bool;
|
||||
}
|
||||
inline constexpr bool has_customization<T> = true;
|
||||
|
||||
struct fn {
|
||||
template<typename T>
|
||||
constexpr bool operator()(const T&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires treat_as_floating_point<T>
|
||||
constexpr bool operator()(const T& value) const
|
||||
{
|
||||
return std::isfinite(value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires treat_as_floating_point<T> && has_customization<T>
|
||||
constexpr bool operator()(const T& value) const
|
||||
{
|
||||
return isfinite(value); // uses ADL
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline constexpr isfinite_impl::fn isfinite{};
|
||||
|
||||
}
|
@@ -24,7 +24,7 @@
|
||||
|
||||
#include <units/bits/hacks.h>
|
||||
#include <units/bits/numeric_concepts.h>
|
||||
#include <units/bits/customization_points.h>
|
||||
#include <units/customization_points.h>
|
||||
#include <units/ratio.h>
|
||||
|
||||
namespace units {
|
115
src/include/units/customization_points.h
Normal file
115
src/include/units/customization_points.h
Normal file
@@ -0,0 +1,115 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
|
||||
namespace units {
|
||||
|
||||
// treat_as_floating_point
|
||||
|
||||
template<typename Rep> // TODO Conceptify that
|
||||
inline constexpr bool treat_as_floating_point = std::is_floating_point_v<Rep>;
|
||||
|
||||
// // isnan
|
||||
// namespace isnan_impl {
|
||||
|
||||
// // non-ADL lookup block
|
||||
// void isnan(); // undefined
|
||||
|
||||
// template<typename>
|
||||
// inline constexpr bool has_customization = false;
|
||||
|
||||
// template<typename T>
|
||||
// requires requires(const T& t) {
|
||||
// { isnan(t) } -> bool;
|
||||
// }
|
||||
// inline constexpr bool has_customization<T> = true;
|
||||
|
||||
// struct fn {
|
||||
// template<typename T>
|
||||
// constexpr bool operator()(const T&) const
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// template<typename T>
|
||||
// requires treat_as_floating_point<T>
|
||||
// constexpr bool operator()(const T& value) const
|
||||
// {
|
||||
// return std::isnan(value);
|
||||
// }
|
||||
|
||||
// template<typename T>
|
||||
// requires treat_as_floating_point<T> && has_customization<T>
|
||||
// constexpr bool operator()(const T& value) const
|
||||
// {
|
||||
// return isnan(value); // uses ADL
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
// inline constexpr isnan_impl::fn isnan{};
|
||||
|
||||
// // isfinite
|
||||
// namespace isfinite_impl {
|
||||
|
||||
// // non-ADL lookup block
|
||||
// void isfinite(); // undefined
|
||||
|
||||
// template<typename>
|
||||
// inline constexpr bool has_customization = false;
|
||||
|
||||
// template<typename T>
|
||||
// requires requires(const T& t) {
|
||||
// { isfinite(t) } -> bool;
|
||||
// }
|
||||
// inline constexpr bool has_customization<T> = true;
|
||||
|
||||
// struct fn {
|
||||
// template<typename T>
|
||||
// constexpr bool operator()(const T&) const
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// template<typename T>
|
||||
// requires treat_as_floating_point<T>
|
||||
// constexpr bool operator()(const T& value) const
|
||||
// {
|
||||
// return std::isfinite(value);
|
||||
// }
|
||||
|
||||
// template<typename T>
|
||||
// requires treat_as_floating_point<T> && has_customization<T>
|
||||
// constexpr bool operator()(const T& value) const
|
||||
// {
|
||||
// return isfinite(value); // uses ADL
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
// inline constexpr isfinite_impl::fn isfinite{};
|
||||
|
||||
}
|
@@ -277,10 +277,14 @@ struct dim_invert_impl<derived_dimension<Es...>> {
|
||||
using type = downcast<derived_dimension<exp_invert<Es>...>>;
|
||||
};
|
||||
|
||||
template<DerivedDimension D>
|
||||
struct dim_invert_impl<D> : dim_invert_impl<downcast_base_t<D>> {
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<Dimension D>
|
||||
using dim_invert = detail::dim_invert_impl<downcast_base_t<D>>::type;
|
||||
using dim_invert = detail::dim_invert_impl<D>::type;
|
||||
|
||||
// dimension_multiply
|
||||
namespace detail {
|
||||
@@ -377,7 +381,7 @@ struct dimension_pow_impl;
|
||||
|
||||
template<BaseDimension D, std::size_t N>
|
||||
struct dimension_pow_impl<D, N> {
|
||||
using type = derived_dimension<exp<D, N>>;
|
||||
using type = downcast<derived_dimension<exp<D, N>>>;
|
||||
};
|
||||
|
||||
template<BaseDimension D, std::size_t N>
|
||||
@@ -387,7 +391,7 @@ struct dimension_pow_impl<exp<D, 1, N>, N> {
|
||||
|
||||
template<DerivedDimension D, std::size_t N>
|
||||
struct dimension_pow_impl<D, N> {
|
||||
using type = dimension_pow_impl<typename D::base_type, N>;
|
||||
using type = dimension_pow_impl<downcast_base<D>, N>;
|
||||
};
|
||||
|
||||
template<typename... Es, std::size_t N>
|
||||
|
@@ -1,64 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/dimensions/length.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
struct area : derived_dimension<area, exp<length, 2>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Area = QuantityOf<T, area>;
|
||||
|
||||
struct square_metre : coherent_derived_unit<square_metre, area> {};
|
||||
struct square_millimetre : deduced_derived_unit<square_millimetre, area, millimetre> {};
|
||||
struct square_centimetre : deduced_derived_unit<square_centimetre, area, centimetre> {};
|
||||
struct square_kilometre : deduced_derived_unit<square_kilometre, area, kilometre> {};
|
||||
struct square_foot : deduced_derived_unit<square_foot, area, foot> {};
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// sq_m
|
||||
constexpr auto operator""sq_m(unsigned long long l) { return quantity<square_metre, std::int64_t>(l); }
|
||||
constexpr auto operator""sq_m(long double l) { return quantity<square_metre, long double>(l); }
|
||||
|
||||
// sq_mm
|
||||
constexpr auto operator""sq_mm(unsigned long long l) { return quantity<square_millimetre, std::int64_t>(l); }
|
||||
constexpr auto operator""sq_mm(long double l) { return quantity<square_millimetre, long double>(l); }
|
||||
|
||||
// sq_cm
|
||||
constexpr auto operator""sq_cm(unsigned long long l) { return quantity<square_centimetre, std::int64_t>(l); }
|
||||
constexpr auto operator""sq_cm(long double l) { return quantity<square_centimetre, long double>(l); }
|
||||
|
||||
// sq_km
|
||||
constexpr auto operator""sq_km(unsigned long long l) { return quantity<square_kilometre, std::int64_t>(l); }
|
||||
constexpr auto operator""sq_km(long double l) { return quantity<square_kilometre, long double>(l); }
|
||||
|
||||
// sq_ft
|
||||
constexpr auto operator""sq_ft(unsigned long long l) { return quantity<square_foot, std::int64_t>(l); }
|
||||
constexpr auto operator""sq_ft(long double l) { return quantity<square_foot, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace units
|
@@ -1,71 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/dimensions/si_base_dimensions.h>
|
||||
#include <units/dimensions/si_prefixes.h>
|
||||
#include <units/dimensions/time.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
struct frequency : derived_dimension<frequency, exp<time, -1>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Frequency = QuantityOf<T, frequency>;
|
||||
|
||||
struct hertz : named_coherent_derived_unit<hertz, frequency, "Hz", si_prefix> {};
|
||||
struct millihertz : prefixed_derived_unit<millihertz, milli, hertz> {};
|
||||
struct kilohertz : prefixed_derived_unit<kilohertz, kilo, hertz> {};
|
||||
struct megahertz : prefixed_derived_unit<megahertz, mega, hertz> {};
|
||||
struct gigahertz : prefixed_derived_unit<gigahertz, giga, hertz> {};
|
||||
struct terahertz : prefixed_derived_unit<terahertz, tera, hertz> {};
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// Hz
|
||||
constexpr auto operator""Hz(unsigned long long l) { return quantity<hertz, std::int64_t>(l); }
|
||||
constexpr auto operator""Hz(long double l) { return quantity<hertz, long double>(l); }
|
||||
|
||||
// mHz
|
||||
constexpr auto operator""mHz(unsigned long long l) { return quantity<millihertz, std::int64_t>(l); }
|
||||
constexpr auto operator""mHz(long double l) { return quantity<millihertz, long double>(l); }
|
||||
|
||||
// kHz
|
||||
constexpr auto operator""kHz(unsigned long long l) { return quantity<kilohertz, std::int64_t>(l); }
|
||||
constexpr auto operator""kHz(long double l) { return quantity<kilohertz, long double>(l); }
|
||||
|
||||
// MHz
|
||||
constexpr auto operator""MHz(unsigned long long l) { return quantity<megahertz, std::int64_t>(l); }
|
||||
constexpr auto operator""MHz(long double l) { return quantity<megahertz, long double>(l); }
|
||||
|
||||
// GHz
|
||||
constexpr auto operator""GHz(unsigned long long l) { return quantity<gigahertz, std::int64_t>(l); }
|
||||
constexpr auto operator""GHz(long double l) { return quantity<gigahertz, long double>(l); }
|
||||
|
||||
// THz
|
||||
constexpr auto operator""THz(unsigned long long l) { return quantity<terahertz, std::int64_t>(l); }
|
||||
constexpr auto operator""THz(long double l) { return quantity<terahertz, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace units
|
@@ -1,88 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/dimensions/si_base_dimensions.h>
|
||||
#include <units/dimensions/si_prefixes.h>
|
||||
#include <units/quantity.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
struct length : derived_dimension<length, exp<base_dim_length, 1>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Length = QuantityOf<T, length>;
|
||||
|
||||
// SI units
|
||||
struct metre : named_coherent_derived_unit<metre, length, "m", si_prefix> {};
|
||||
struct millimetre : prefixed_derived_unit<millimetre, milli, metre> {};
|
||||
struct centimetre : prefixed_derived_unit<centimetre, centi, metre> {};
|
||||
struct kilometre : prefixed_derived_unit<kilometre, kilo, metre> {};
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// m
|
||||
constexpr auto operator""m(unsigned long long l) { return quantity<metre, std::int64_t>(l); }
|
||||
constexpr auto operator""m(long double l) { return quantity<metre, long double>(l); }
|
||||
|
||||
// mm
|
||||
constexpr auto operator""mm(unsigned long long l) { return quantity<millimetre, std::int64_t>(l); }
|
||||
constexpr auto operator""mm(long double l) { return quantity<millimetre, long double>(l); }
|
||||
|
||||
// cm
|
||||
constexpr auto operator""cm(unsigned long long l) { return quantity<centimetre, std::int64_t>(l); }
|
||||
constexpr auto operator""cm(long double l) { return quantity<centimetre, long double>(l); }
|
||||
|
||||
// km
|
||||
constexpr auto operator""km(unsigned long long l) { return quantity<kilometre, std::int64_t>(l); }
|
||||
constexpr auto operator""km(long double l) { return quantity<kilometre, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
// US customary units
|
||||
struct yard : named_scaled_derived_unit<yard, length, "yd", ratio<9'144, 10'000>> {};
|
||||
struct foot : named_scaled_derived_unit<foot, length, "ft", ratio_divide<yard::ratio, ratio<3>>> {};
|
||||
struct inch : named_scaled_derived_unit<inch, length, "in", ratio_divide<foot::ratio, ratio<12>>> {};
|
||||
struct mile : named_scaled_derived_unit<mile, length, "mi", ratio_multiply<ratio<1'760>, yard::ratio>> {};
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// yd
|
||||
constexpr auto operator""yd(unsigned long long l) { return quantity<yard, std::int64_t>(l); }
|
||||
constexpr auto operator""yd(long double l) { return quantity<yard, long double>(l); }
|
||||
|
||||
// ft
|
||||
constexpr auto operator""ft(unsigned long long l) { return quantity<foot, std::int64_t>(l); }
|
||||
constexpr auto operator""ft(long double l) { return quantity<foot, long double>(l); }
|
||||
|
||||
// in
|
||||
constexpr auto operator""in(unsigned long long l) { return quantity<inch, std::int64_t>(l); }
|
||||
constexpr auto operator""in(long double l) { return quantity<inch, long double>(l); }
|
||||
|
||||
// mi
|
||||
constexpr auto operator""mi(unsigned long long l) { return quantity<mile, std::int64_t>(l); }
|
||||
constexpr auto operator""mi(long double l) { return quantity<mile, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace units
|
124
src/include/units/dimensions/physical.h
Normal file
124
src/include/units/dimensions/physical.h
Normal file
@@ -0,0 +1,124 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/dimensions/si_base_dimensions.h>
|
||||
#include <units/dimensions/si_prefixes.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
// base dimension
|
||||
|
||||
template<basic_fixed_string Name>
|
||||
struct base_dimension {
|
||||
static constexpr auto name = Name;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept BaseDimension = true;
|
||||
|
||||
// base dimension
|
||||
|
||||
template<basic_fixed_string Symbol, BaseDimension Dim, PrefixType PT, Ratio R = ratio<1>>
|
||||
struct base_unit {
|
||||
static constexpr auto symbol = Symbol;
|
||||
using dimension = Dim;
|
||||
using prefix_type = PT;
|
||||
using ratio = R;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept BaseUnit = true;
|
||||
|
||||
template<typename T, typename Dim>
|
||||
concept BaseUnitOf = BaseUnit<T> && BaseDimension<Dim> && std::same_as<typename T::dimension, Dim>;
|
||||
|
||||
|
||||
|
||||
namespace physical {
|
||||
|
||||
// base dimensions
|
||||
struct base_dim_length : base_dimension<"length"> {};
|
||||
struct base_dim_mass : base_dimension<"mass"> {};
|
||||
struct base_dim_time : base_dimension<"time"> {};
|
||||
struct base_dim_current : base_dimension<"current"> {};
|
||||
struct base_dim_temperature : base_dimension<"temperature"> {};
|
||||
struct base_dim_substance : base_dimension<"substance"> {};
|
||||
struct base_dim_luminous_intensity : base_dimension<"luminous intensity"> {};
|
||||
|
||||
|
||||
// dimensions
|
||||
template<UnitOf<base_dim_length> L>
|
||||
struct length : derived_dimension<length, exp<L, 1>> {};
|
||||
|
||||
template<UnitOf<base_dim_mass> M>
|
||||
struct mass : derived_dimension<mass, exp<M, 1>> {};
|
||||
|
||||
template<UnitOf<base_dim_time> T>
|
||||
struct time : derived_dimension<time, exp<T, 1>> {};
|
||||
|
||||
template<UnitOf<base_dim_length> L, UnitOf<base_dim_time> T>
|
||||
struct velocity : derived_dimension<velocity, exp<L, 1>, exp<T, -1>> {};
|
||||
|
||||
template<UnitOf<base_dim_length> L, UnitOf<base_dim_time> T>
|
||||
struct acceleration : derived_dimension<acceleration, exp<L, 1>, exp<T, -2>> {};
|
||||
|
||||
template<UnitOf<base_dim_mass> M, UnitOf<acceleration> A>
|
||||
struct force : derived_dimension<force, exp<M, 1>, exp<A, 1>> {};
|
||||
|
||||
} // physical
|
||||
|
||||
// SI
|
||||
namespace si {
|
||||
struct si_prefix;
|
||||
|
||||
// length
|
||||
struct metre : base_unit<"m", base_dim_length, si_prefix> {};
|
||||
struct length : physical::length<metre> {};
|
||||
|
||||
// mass
|
||||
struct kilogram : base_unit<"kg", base_dim_mass, si_prefix> {};
|
||||
struct mass : physical::mass<kilogram> {};
|
||||
|
||||
// time
|
||||
struct second : base_unit<"s", base_dim_time, si_prefix> {};
|
||||
struct time : physical::time<second> {};
|
||||
|
||||
struct nanosecond : prefixed_derived_unit<nanosecond, nano, second> {};
|
||||
struct microsecond : prefixed_derived_unit<microsecond, micro, second> {};
|
||||
struct millisecond : prefixed_derived_unit<millisecond, milli, second> {};
|
||||
struct minute : named_derived_unit<minute, time, "min", ratio<60>> {};
|
||||
struct hour : named_derived_unit<hour, time, "h", ratio<3600>> {};
|
||||
|
||||
// velocity
|
||||
struct velocity : physical::velocity<metre, second>;
|
||||
|
||||
// acceleration
|
||||
struct acceleration : physical::acceleration<metre, second>;
|
||||
|
||||
// acceleration
|
||||
struct acceleration : physical::acceleration<metre, second>;
|
||||
|
||||
}
|
||||
|
||||
} // namespace units
|
@@ -1,37 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/dimension.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
struct base_dim_length : base_dimension<"length", "m"> {};
|
||||
struct base_dim_mass : base_dimension<"mass", "kg"> {};
|
||||
struct base_dim_time : base_dimension<"time", "s"> {};
|
||||
struct base_dim_current : base_dimension<"current", "A"> {};
|
||||
struct base_dim_temperature : base_dimension<"temperature", "K"> {};
|
||||
struct base_dim_substance : base_dimension<"substance", "mol"> {};
|
||||
struct base_dim_luminous_intensity : base_dimension<"luminous intensity", "cd"> {};
|
||||
|
||||
} // namespace units
|
@@ -1,71 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/dimensions/si_base_dimensions.h>
|
||||
#include <units/dimensions/si_prefixes.h>
|
||||
#include <units/quantity.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
struct time : derived_dimension<time, exp<base_dim_time, 1>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Time = QuantityOf<T, time>;
|
||||
|
||||
struct second : named_coherent_derived_unit<second, time, "s", si_prefix> {};
|
||||
struct nanosecond : prefixed_derived_unit<nanosecond, nano, second> {};
|
||||
struct microsecond : prefixed_derived_unit<microsecond, micro, second> {};
|
||||
struct millisecond : prefixed_derived_unit<millisecond, milli, second> {};
|
||||
struct minute : named_scaled_derived_unit<minute, time, "min", ratio<60>> {};
|
||||
struct hour : named_scaled_derived_unit<hour, time, "h", ratio<3600>> {};
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// ns
|
||||
constexpr auto operator""ns(unsigned long long l) { return quantity<nanosecond, std::int64_t>(l); }
|
||||
constexpr auto operator""ns(long double l) { return quantity<nanosecond, long double>(l); }
|
||||
|
||||
// us
|
||||
constexpr auto operator""us(unsigned long long l) { return quantity<microsecond, std::int64_t>(l); }
|
||||
constexpr auto operator""us(long double l) { return quantity<microsecond, long double>(l); }
|
||||
|
||||
// ms
|
||||
constexpr auto operator""ms(unsigned long long l) { return quantity<millisecond, std::int64_t>(l); }
|
||||
constexpr auto operator""ms(long double l) { return quantity<millisecond, long double>(l); }
|
||||
|
||||
// s
|
||||
constexpr auto operator""s(unsigned long long l) { return quantity<second, std::int64_t>(l); }
|
||||
constexpr auto operator""s(long double l) { return quantity<second, long double>(l); }
|
||||
|
||||
// min
|
||||
constexpr auto operator""min(unsigned long long l) { return quantity<minute, std::int64_t>(l); }
|
||||
constexpr auto operator""min(long double l) { return quantity<minute, long double>(l); }
|
||||
|
||||
// h
|
||||
constexpr auto operator""h(unsigned long long l) { return quantity<hour, std::int64_t>(l); }
|
||||
constexpr auto operator""h(long double l) { return quantity<hour, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace units
|
@@ -1,55 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/dimensions/length.h>
|
||||
#include <units/dimensions/time.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
struct velocity : derived_dimension<velocity, exp<length, 1>, exp<time, -1>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Velocity = QuantityOf<T, velocity>;
|
||||
|
||||
struct metre_per_second : coherent_derived_unit<metre_per_second, velocity> {};
|
||||
struct kilometre_per_hour : deduced_derived_unit<kilometre_per_hour, velocity, kilometre, hour> {};
|
||||
struct mile_per_hour : deduced_derived_unit<mile_per_hour, velocity, mile, hour> {};
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// mps
|
||||
constexpr auto operator""mps(unsigned long long l) { return quantity<metre_per_second, std::int64_t>(l); }
|
||||
constexpr auto operator""mps(long double l) { return quantity<metre_per_second, long double>(l); }
|
||||
|
||||
// kmph
|
||||
constexpr auto operator""kmph(unsigned long long l) { return quantity<kilometre_per_hour, std::int64_t>(l); }
|
||||
constexpr auto operator""kmph(long double l) { return quantity<kilometre_per_hour, long double>(l); }
|
||||
|
||||
// mph
|
||||
constexpr auto operator""mph(unsigned long long l) { return quantity<mile_per_hour, std::int64_t>(l); }
|
||||
constexpr auto operator""mph(long double l) { return quantity<mile_per_hour, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace units
|
@@ -27,27 +27,27 @@
|
||||
|
||||
namespace units {
|
||||
|
||||
template<std::size_t N, typename U, typename Rep>
|
||||
template<std::size_t N, typename D, typename U, typename Rep>
|
||||
requires N == 0
|
||||
inline Rep AUTO pow(const quantity<U, Rep>&) noexcept
|
||||
inline Rep AUTO pow(const quantity<D, U, Rep>&) noexcept
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<std::size_t N, typename U, typename Rep>
|
||||
inline Quantity AUTO pow(const quantity<U, Rep>& q) noexcept
|
||||
template<std::size_t N, typename D, typename U, typename Rep>
|
||||
inline Quantity AUTO pow(const quantity<D, U, Rep>& q) noexcept
|
||||
{
|
||||
using dim = dimension_pow<typename U::dimension, N>;
|
||||
using dim = dimension_pow<D, N>;
|
||||
using r = ratio_pow<typename U::ratio, N>;
|
||||
return quantity<downcast<unit<dim, r>>, Rep>(static_cast<Rep>(std::pow(q.count(), N)));
|
||||
return quantity<dim, downcast<detail::reference_unit<typename dim::coherent_unit::reference, r>>, Rep>(static_cast<Rep>(std::pow(q.count(), N)));
|
||||
}
|
||||
|
||||
template<typename U, typename Rep>
|
||||
inline Quantity AUTO sqrt(const quantity<U, Rep>& q) noexcept
|
||||
template<typename D, typename U, typename Rep>
|
||||
inline Quantity AUTO sqrt(const quantity<D, U, Rep>& q) noexcept
|
||||
{
|
||||
using dim = dimension_sqrt<typename U::dimension>;
|
||||
using r = ratio_sqrt<typename U::ratio>;
|
||||
return quantity<downcast<unit<dim, r>>, Rep>(static_cast<Rep>(std::sqrt(q.count())));
|
||||
return quantity<dim, downcast<detail::reference_unit<typename dim::coherent_unit::reference, r>>, Rep>(static_cast<Rep>(std::sqrt(q.count())));
|
||||
}
|
||||
|
||||
} // namespace units
|
||||
|
151
src/include/units/physical/dimensions.h
Normal file
151
src/include/units/physical/dimensions.h
Normal file
@@ -0,0 +1,151 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/base_dimension.h>
|
||||
#include <units/bits/type_traits.h>
|
||||
#include <units/quantity.h>
|
||||
#include <units/unit.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
inline namespace physical {
|
||||
|
||||
template<typename Dim, template<typename...> typename DimTemplate>
|
||||
concept DimensionOf = (Dimension<Dim> || BaseDimension<Dim>) && is_derived_from_instantiation<Dim, DimTemplate>;
|
||||
|
||||
template<typename Q, template<typename...> typename DimTemplate>
|
||||
concept QuantityOf = Quantity<Q> && is_derived_from_instantiation<Q::dimension, DimTemplate>;
|
||||
|
||||
// ------------------------ base dimensions -----------------------------
|
||||
|
||||
// length
|
||||
template<Unit U>
|
||||
struct dim_length : base_dimension<"length", U> {};
|
||||
|
||||
template<typename T>
|
||||
concept Length = QuantityOf<T, dim_length>;
|
||||
|
||||
// mass
|
||||
template<Unit U>
|
||||
struct dim_mass : base_dimension<"mass", U> {};
|
||||
|
||||
template<typename T>
|
||||
concept Mass = QuantityOf<T, dim_mass>;
|
||||
|
||||
// time
|
||||
template<Unit U>
|
||||
struct dim_time : base_dimension<"time", U> {};
|
||||
|
||||
template<typename T>
|
||||
concept Time = QuantityOf<T, dim_time>;
|
||||
|
||||
// current
|
||||
template<Unit U>
|
||||
struct dim_current : base_dimension<"current", U> {};
|
||||
|
||||
template<typename T>
|
||||
concept Current = QuantityOf<T, dim_current>;
|
||||
|
||||
// temperature
|
||||
template<Unit U>
|
||||
struct dim_temperature : base_dimension<"temperature", U> {};
|
||||
|
||||
template<typename T>
|
||||
concept Temperature = QuantityOf<T, dim_temperature>;
|
||||
|
||||
// substance
|
||||
template<Unit U>
|
||||
struct dim_substance : base_dimension<"substance", U> {};
|
||||
|
||||
template<typename T>
|
||||
concept Substance = QuantityOf<T, dim_substance>;
|
||||
|
||||
// luminous intensity
|
||||
template<Unit U>
|
||||
struct dim_luminous_intensity : base_dimension<"luminous intensity", U> {};
|
||||
|
||||
template<typename T>
|
||||
concept LuminousIntensity = QuantityOf<T, dim_luminous_intensity>;
|
||||
|
||||
// ------------------------ derived dimensions -----------------------------
|
||||
|
||||
// frequency
|
||||
template<typename Child, Unit U, DimensionOf<dim_time> T>
|
||||
struct dim_frequency : derived_dimension<Child, U, exp<T, -1>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Frequency = QuantityOf<T, dim_frequency>;
|
||||
|
||||
// area
|
||||
template<typename Child, Unit U, DimensionOf<dim_length> L>
|
||||
struct dim_area : derived_dimension<Child, U, exp<L, 2>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Area = QuantityOf<T, dim_area>;
|
||||
|
||||
// velocity
|
||||
template<typename Child, Unit U, DimensionOf<dim_length> L, DimensionOf<dim_time> T>
|
||||
struct dim_velocity : derived_dimension<Child, U, exp<L, 1>, exp<T, -1>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Velocity = QuantityOf<T, dim_velocity>;
|
||||
|
||||
// acceleration
|
||||
template<typename Child, Unit U, DimensionOf<dim_length> L, DimensionOf<dim_time> T>
|
||||
struct dim_acceleration : derived_dimension<Child, U, exp<L, 1>, exp<T, -2>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Acceleration = QuantityOf<T, dim_acceleration>;
|
||||
|
||||
// force
|
||||
template<typename Child, Unit U, DimensionOf<dim_mass> M, DimensionOf<dim_acceleration> A>
|
||||
struct dim_force : derived_dimension<Child, U, exp<M, 1>, exp<A, 1>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Force = QuantityOf<T, dim_force>;
|
||||
|
||||
// energy
|
||||
template<typename Child, Unit U, DimensionOf<dim_force> F, DimensionOf<dim_length> L>
|
||||
struct dim_energy : derived_dimension<Child, U, exp<F, 1>, exp<L, 1>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Energy = QuantityOf<T, dim_energy>;
|
||||
|
||||
// power
|
||||
template<typename Child, Unit U, DimensionOf<dim_energy> E, DimensionOf<dim_time> T>
|
||||
struct dim_power : derived_dimension<Child, U, exp<E, 1>, exp<T, -1>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Power = QuantityOf<T, dim_power>;
|
||||
|
||||
// pressure
|
||||
template<typename Child, Unit U, DimensionOf<dim_force> F, DimensionOf<dim_area> A>
|
||||
struct dim_pressure : derived_dimension<Child, U, exp<F, 1>, exp<A, -1>> {};
|
||||
|
||||
template<typename T>
|
||||
concept Pressure = QuantityOf<T, dim_pressure>;
|
||||
|
||||
} // namespace physical
|
||||
|
||||
} // namespace units
|
65
src/include/units/physical/si/area.h
Normal file
65
src/include/units/physical/si/area.h
Normal file
@@ -0,0 +1,65 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/physical/dimensions.h>
|
||||
#include <units/physical/si/length.h>
|
||||
|
||||
namespace units::si {
|
||||
|
||||
struct square_metre : unit<square_metre> {};
|
||||
struct dim_area : physical::dim_area<dim_area, square_metre, dim_length> {};
|
||||
|
||||
struct square_millimetre : deduced_unit<square_millimetre, dim_area, millimetre> {};
|
||||
struct square_centimetre : deduced_unit<square_centimetre, dim_area, centimetre> {};
|
||||
struct square_kilometre : deduced_unit<square_kilometre, dim_area, kilometre> {};
|
||||
struct square_foot : deduced_unit<square_foot, dim_area, foot> {};
|
||||
|
||||
template<Unit U, Scalar Rep = double>
|
||||
using area = quantity<dim_area, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// sq_m
|
||||
constexpr auto operator"" sq_m(unsigned long long l) { return area<square_metre, std::int64_t>(l); }
|
||||
constexpr auto operator"" sq_m(long double l) { return area<square_metre, long double>(l); }
|
||||
|
||||
// sq_mm
|
||||
constexpr auto operator"" sq_mm(unsigned long long l) { return area<square_millimetre, std::int64_t>(l); }
|
||||
constexpr auto operator"" sq_mm(long double l) { return area<square_millimetre, long double>(l); }
|
||||
|
||||
// sq_cm
|
||||
constexpr auto operator"" sq_cm(unsigned long long l) { return area<square_centimetre, std::int64_t>(l); }
|
||||
constexpr auto operator"" sq_cm(long double l) { return area<square_centimetre, long double>(l); }
|
||||
|
||||
// sq_km
|
||||
constexpr auto operator"" sq_km(unsigned long long l) { return area<square_kilometre, std::int64_t>(l); }
|
||||
constexpr auto operator"" sq_km(long double l) { return area<square_kilometre, long double>(l); }
|
||||
|
||||
// sq_ft
|
||||
constexpr auto operator"" sq_ft(unsigned long long l) { return area<square_foot, std::int64_t>(l); }
|
||||
constexpr auto operator"" sq_ft(long double l) { return area<square_foot, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace units::si
|
70
src/include/units/physical/si/frequency.h
Normal file
70
src/include/units/physical/si/frequency.h
Normal file
@@ -0,0 +1,70 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/physical/dimensions.h>
|
||||
#include <units/physical/si/time.h>
|
||||
|
||||
namespace units::si {
|
||||
|
||||
struct hertz : named_unit<hertz, "Hz", prefix> {};
|
||||
struct millihertz : prefixed_unit<millihertz, milli, hertz> {};
|
||||
struct kilohertz : prefixed_unit<kilohertz, kilo, hertz> {};
|
||||
struct megahertz : prefixed_unit<megahertz, mega, hertz> {};
|
||||
struct gigahertz : prefixed_unit<gigahertz, giga, hertz> {};
|
||||
struct terahertz : prefixed_unit<terahertz, tera, hertz> {};
|
||||
|
||||
struct dim_frequency : physical::dim_frequency<dim_frequency, hertz, dim_time> {};
|
||||
|
||||
template<Unit U, Scalar Rep = double>
|
||||
using frequency = quantity<dim_frequency, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// Hz
|
||||
constexpr auto operator"" Hz(unsigned long long l) { return frequency<hertz, std::int64_t>(l); }
|
||||
constexpr auto operator"" Hz(long double l) { return frequency<hertz, long double>(l); }
|
||||
|
||||
// mHz
|
||||
constexpr auto operator"" mHz(unsigned long long l) { return frequency<millihertz, std::int64_t>(l); }
|
||||
constexpr auto operator"" mHz(long double l) { return frequency<millihertz, long double>(l); }
|
||||
|
||||
// kHz
|
||||
constexpr auto operator"" kHz(unsigned long long l) { return frequency<kilohertz, std::int64_t>(l); }
|
||||
constexpr auto operator"" kHz(long double l) { return frequency<kilohertz, long double>(l); }
|
||||
|
||||
// MHz
|
||||
constexpr auto operator"" MHz(unsigned long long l) { return frequency<megahertz, std::int64_t>(l); }
|
||||
constexpr auto operator"" MHz(long double l) { return frequency<megahertz, long double>(l); }
|
||||
|
||||
// GHz
|
||||
constexpr auto operator"" GHz(unsigned long long l) { return frequency<gigahertz, std::int64_t>(l); }
|
||||
constexpr auto operator"" GHz(long double l) { return frequency<gigahertz, long double>(l); }
|
||||
|
||||
// THz
|
||||
constexpr auto operator"" THz(unsigned long long l) { return frequency<terahertz, std::int64_t>(l); }
|
||||
constexpr auto operator"" THz(long double l) { return frequency<terahertz, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace units::si
|
86
src/include/units/physical/si/length.h
Normal file
86
src/include/units/physical/si/length.h
Normal file
@@ -0,0 +1,86 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/physical/dimensions.h>
|
||||
#include <units/physical/si/prefixes.h>
|
||||
|
||||
namespace units::si {
|
||||
|
||||
struct metre : named_unit<metre, "m", prefix> {};
|
||||
struct millimetre : prefixed_unit<millimetre, milli, metre> {};
|
||||
struct centimetre : prefixed_unit<centimetre, centi, metre> {};
|
||||
struct kilometre : prefixed_unit<kilometre, kilo, metre> {};
|
||||
|
||||
struct dim_length : physical::dim_length<metre> {};
|
||||
|
||||
template<Unit U, Scalar Rep = double>
|
||||
using length = quantity<dim_length, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// m
|
||||
constexpr auto operator"" m(unsigned long long l) { return length<metre, std::int64_t>(l); }
|
||||
constexpr auto operator"" m(long double l) { return length<metre, long double>(l); }
|
||||
|
||||
// mm
|
||||
constexpr auto operator"" mm(unsigned long long l) { return length<millimetre, std::int64_t>(l); }
|
||||
constexpr auto operator"" mm(long double l) { return length<millimetre, long double>(l); }
|
||||
|
||||
// cm
|
||||
constexpr auto operator"" cm(unsigned long long l) { return length<centimetre, std::int64_t>(l); }
|
||||
constexpr auto operator"" cm(long double l) { return length<centimetre, long double>(l); }
|
||||
|
||||
// km
|
||||
constexpr auto operator"" km(unsigned long long l) { return length<kilometre, std::int64_t>(l); }
|
||||
constexpr auto operator"" km(long double l) { return length<kilometre, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
// US customary units
|
||||
struct yard : scaled_unit<yard, "yd", no_prefix, ratio<9'144, 10'000>, metre> {};
|
||||
struct foot : scaled_unit<foot, "ft", no_prefix, ratio<1, 3>, yard> {};
|
||||
struct inch : scaled_unit<inch, "in", no_prefix, ratio<1, 12>, foot> {};
|
||||
struct mile : scaled_unit<mile, "mi", no_prefix, ratio<1'760>, yard> {};
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// yd
|
||||
constexpr auto operator"" yd(unsigned long long l) { return length<yard, std::int64_t>(l); }
|
||||
constexpr auto operator"" yd(long double l) { return length<yard, long double>(l); }
|
||||
|
||||
// ft
|
||||
constexpr auto operator"" ft(unsigned long long l) { return length<foot, std::int64_t>(l); }
|
||||
constexpr auto operator"" ft(long double l) { return length<foot, long double>(l); }
|
||||
|
||||
// in
|
||||
constexpr auto operator"" in(unsigned long long l) { return length<inch, std::int64_t>(l); }
|
||||
constexpr auto operator"" in(long double l) { return length<inch, long double>(l); }
|
||||
|
||||
// mi
|
||||
constexpr auto operator"" mi(unsigned long long l) { return length<mile, std::int64_t>(l); }
|
||||
constexpr auto operator"" mi(long double l) { return length<mile, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace units::si
|
70
src/include/units/physical/si/time.h
Normal file
70
src/include/units/physical/si/time.h
Normal file
@@ -0,0 +1,70 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/physical/dimensions.h>
|
||||
#include <units/physical/si/prefixes.h>
|
||||
|
||||
namespace units::si {
|
||||
|
||||
struct second : named_unit<second, "s", prefix> {};
|
||||
struct nanosecond : prefixed_unit<nanosecond, nano, second> {};
|
||||
struct microsecond : prefixed_unit<microsecond, micro, second> {};
|
||||
struct millisecond : prefixed_unit<millisecond, milli, second> {};
|
||||
struct minute : scaled_unit<minute, "min", no_prefix, ratio<60>, second> {};
|
||||
struct hour : scaled_unit<hour, "h", no_prefix, ratio<3600>, second> {};
|
||||
|
||||
struct dim_time : physical::dim_time<second> {};
|
||||
|
||||
template<Unit U, Scalar Rep = double>
|
||||
using time = quantity<dim_time, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// ns
|
||||
constexpr auto operator""ns(unsigned long long l) { return time<nanosecond, std::int64_t>(l); }
|
||||
constexpr auto operator""ns(long double l) { return time<nanosecond, long double>(l); }
|
||||
|
||||
// us
|
||||
constexpr auto operator""us(unsigned long long l) { return time<microsecond, std::int64_t>(l); }
|
||||
constexpr auto operator""us(long double l) { return time<microsecond, long double>(l); }
|
||||
|
||||
// ms
|
||||
constexpr auto operator""ms(unsigned long long l) { return time<millisecond, std::int64_t>(l); }
|
||||
constexpr auto operator""ms(long double l) { return time<millisecond, long double>(l); }
|
||||
|
||||
// s
|
||||
constexpr auto operator""s(unsigned long long l) { return time<second, std::int64_t>(l); }
|
||||
constexpr auto operator""s(long double l) { return time<second, long double>(l); }
|
||||
|
||||
// min
|
||||
constexpr auto operator""min(unsigned long long l) { return time<minute, std::int64_t>(l); }
|
||||
constexpr auto operator""min(long double l) { return time<minute, long double>(l); }
|
||||
|
||||
// h
|
||||
constexpr auto operator""h(unsigned long long l) { return time<hour, std::int64_t>(l); }
|
||||
constexpr auto operator""h(long double l) { return time<hour, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace units::si
|
56
src/include/units/physical/si/velocity.h
Normal file
56
src/include/units/physical/si/velocity.h
Normal file
@@ -0,0 +1,56 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2018 Mateusz Pusz
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/physical/dimensions.h>
|
||||
#include <units/physical/si/length.h>
|
||||
#include <units/physical/si/time.h>
|
||||
|
||||
namespace units::si {
|
||||
|
||||
struct metre_per_second : unit<metre_per_second> {};
|
||||
struct dim_velocity : physical::dim_velocity<dim_velocity, metre_per_second, dim_length, dim_time> {};
|
||||
|
||||
struct kilometre_per_hour : deduced_unit<kilometre_per_hour, dim_velocity, kilometre, hour> {};
|
||||
struct mile_per_hour : deduced_unit<mile_per_hour, dim_velocity, mile, hour> {};
|
||||
|
||||
template<Unit U, Scalar Rep = double>
|
||||
using velocity = quantity<dim_velocity, U, Rep>;
|
||||
|
||||
inline namespace literals {
|
||||
|
||||
// mps
|
||||
constexpr auto operator"" mps(unsigned long long l) { return velocity<metre_per_second, std::int64_t>(l); }
|
||||
constexpr auto operator"" mps(long double l) { return velocity<metre_per_second, long double>(l); }
|
||||
|
||||
// kmph
|
||||
constexpr auto operator"" kmph(unsigned long long l) { return velocity<kilometre_per_hour, std::int64_t>(l); }
|
||||
constexpr auto operator"" kmph(long double l) { return velocity<kilometre_per_hour, long double>(l); }
|
||||
|
||||
// mph
|
||||
constexpr auto operator"" mph(unsigned long long l) { return velocity<mile_per_hour, std::int64_t>(l); }
|
||||
constexpr auto operator"" mph(long double l) { return velocity<mile_per_hour, long double>(l); }
|
||||
|
||||
} // namespace literals
|
||||
|
||||
} // namespace units::si
|
@@ -22,14 +22,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/concepts.h>
|
||||
#include <units/concepts.h>
|
||||
#include <units/unit.h>
|
||||
#include <limits>
|
||||
#include <ostream>
|
||||
|
||||
namespace units {
|
||||
|
||||
// is_quantity
|
||||
// Quantity
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
@@ -42,24 +42,21 @@ namespace units {
|
||||
template<typename T>
|
||||
concept Quantity = detail::is_quantity<T>;
|
||||
|
||||
// QuantityOf
|
||||
template<typename T, typename Dim>
|
||||
concept QuantityOf = Quantity<T> && Dimension<Dim> && same_dim<typename T::dimension, Dim>;
|
||||
|
||||
// Scalar
|
||||
template<typename T>
|
||||
concept Scalar =
|
||||
(!Quantity<T>) &&
|
||||
std::regular<T> &&
|
||||
std::totally_ordered<T> &&
|
||||
detail::basic_arithmetic<T>;
|
||||
concept Scalar = (!Quantity<T>) && std::regular<T> && std::totally_ordered<T> && detail::basic_arithmetic<T>;
|
||||
|
||||
template<Unit U, Scalar Rep>
|
||||
template<Dimension D, UnitOf<D> U, Scalar Rep>
|
||||
class quantity;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename U, typename Rep>
|
||||
inline constexpr bool is_quantity<quantity<U, Rep>> = true;
|
||||
template<typename D, typename U, typename Rep>
|
||||
inline constexpr bool is_quantity<quantity<D, U, Rep>> = true;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -69,16 +66,15 @@ namespace units {
|
||||
template<typename Q1, typename Q2, typename Rep>
|
||||
struct common_quantity_impl;
|
||||
|
||||
template<typename U, typename Rep1, typename Rep2, typename Rep>
|
||||
struct common_quantity_impl<quantity<U, Rep1>, quantity<U, Rep2>, Rep> {
|
||||
using type = quantity<U, Rep>;
|
||||
template<typename D, typename U, typename Rep1, typename Rep2, typename Rep>
|
||||
struct common_quantity_impl<quantity<D, U, Rep1>, quantity<D, U, Rep2>, Rep> {
|
||||
using type = quantity<D, U, Rep>;
|
||||
};
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2, typename Rep>
|
||||
requires same_dim<typename U1::dimension, typename U2::dimension>
|
||||
struct common_quantity_impl<quantity<U1, Rep1>, quantity<U2, Rep2>, Rep> {
|
||||
using type =
|
||||
quantity<downcast<unit<typename U1::dimension, common_ratio<typename U1::ratio, typename U2::ratio>>>,
|
||||
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2, typename Rep>
|
||||
struct common_quantity_impl<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, Rep> {
|
||||
using type = quantity<
|
||||
D, downcast<detail::reference_unit<typename U1::reference, common_ratio<typename U1::ratio, typename U2::ratio>>>,
|
||||
Rep>;
|
||||
};
|
||||
|
||||
@@ -88,7 +84,6 @@ namespace units {
|
||||
using common_quantity = detail::common_quantity_impl<Q1, Q2, Rep>::type;
|
||||
|
||||
// quantity_cast
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename To, typename CRatio, typename CRep, bool NumIsOne = false, bool DenIsOne = false>
|
||||
@@ -99,10 +94,9 @@ namespace units {
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) *
|
||||
(static_cast<CRep>(CRatio::num) / static_cast<CRep>(CRatio::den))));
|
||||
}
|
||||
else {
|
||||
return To(
|
||||
static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio::num) / static_cast<CRep>(CRatio::den)));
|
||||
} else {
|
||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * static_cast<CRep>(CRatio::num) /
|
||||
static_cast<CRep>(CRatio::den)));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -123,8 +117,7 @@ namespace units {
|
||||
{
|
||||
if constexpr (treat_as_floating_point<CRep>) {
|
||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) * (CRep{1} / static_cast<CRep>(CRatio::den))));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return To(static_cast<To::rep>(static_cast<CRep>(q.count()) / static_cast<CRep>(CRatio::den)));
|
||||
}
|
||||
}
|
||||
@@ -141,63 +134,126 @@ namespace units {
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<Quantity To, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<U, Rep>& q)
|
||||
requires same_dim<typename To::dimension, typename U::dimension> &&
|
||||
/**
|
||||
* @brief Explcit cast of a quantity
|
||||
*
|
||||
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||
*
|
||||
* This cast gets the target quantity type to cast to. For example:
|
||||
*
|
||||
* using seconds = units::time<units::si::second, double>;
|
||||
* auto q1 = units::quantity_cast<seconds>(1ms);
|
||||
*
|
||||
* @tparam To a target quantity type to cast to
|
||||
*/
|
||||
template<Quantity To, typename D, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||
requires QuantityOf<To, D> &&
|
||||
detail::basic_arithmetic<std::common_type_t<typename To::rep, Rep, intmax_t>>
|
||||
{
|
||||
using c_ratio = ratio_divide<typename U::ratio, typename To::unit::ratio>;
|
||||
using c_rep = std::common_type_t<typename To::rep, Rep, intmax_t>;
|
||||
using ret_dim = downcast<typename To::unit::dimension>;
|
||||
using ret_unit = downcast<unit<ret_dim, typename To::unit::ratio>>;
|
||||
using ret = quantity<ret_unit, typename To::rep>;
|
||||
using ret_unit = downcast<detail::reference_unit<typename U::reference, typename To::unit::ratio>>;
|
||||
using ret = quantity<D, ret_unit, typename To::rep>;
|
||||
using cast = detail::quantity_cast_impl<ret, c_ratio, c_rep, c_ratio::num == 1, c_ratio::den == 1>;
|
||||
return cast::cast(q);
|
||||
}
|
||||
|
||||
template<Unit ToU, Scalar ToRep, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<U, Rep>& q)
|
||||
requires same_dim<typename ToU::dimension, typename U::dimension> &&
|
||||
/**
|
||||
* @brief Explcit cast of a quantity
|
||||
*
|
||||
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||
*
|
||||
* This cast gets both the target unit and representation to cast to. For example:
|
||||
*
|
||||
* auto q1 = units::quantity_cast<units::second, int>(1ms);
|
||||
*
|
||||
* @tparam ToU a unit type to use for a target quantity
|
||||
* @tparam ToRep a representation type to use for a target quantity
|
||||
*/
|
||||
template<Unit ToU, Scalar ToRep, typename D, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||
requires UnitOf<ToU, D> &&
|
||||
detail::basic_arithmetic<std::common_type_t<ToRep, Rep, intmax_t>>
|
||||
{
|
||||
return quantity_cast<quantity<ToU, ToRep>>(q);
|
||||
return quantity_cast<quantity<D, ToU, ToRep>>(q);
|
||||
}
|
||||
|
||||
template<Unit ToU, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<U, Rep>& q)
|
||||
requires same_dim<typename ToU::dimension, typename U::dimension>
|
||||
/**
|
||||
* @brief Explcit cast of a quantity
|
||||
*
|
||||
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||
*
|
||||
* This cast gets only the target unit to cast to. For example:
|
||||
*
|
||||
* auto q1 = units::quantity_cast<units::second>(1ms);
|
||||
*
|
||||
* @tparam ToU a unit type to use for a target quantity
|
||||
*/
|
||||
template<Unit ToU, typename D, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||
requires UnitOf<ToU, D>
|
||||
{
|
||||
return quantity_cast<quantity<ToU, Rep>>(q);
|
||||
return quantity_cast<quantity<D, ToU, Rep>>(q);
|
||||
}
|
||||
|
||||
template<Scalar ToRep, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<U, Rep>& q)
|
||||
/**
|
||||
* @brief Explcit cast of a quantity
|
||||
*
|
||||
* Implicit conversions between quantities of different types are allowed only for "safe"
|
||||
* (i.e. non-truncating) conversion. In such cases an explicit cast have to be used.
|
||||
*
|
||||
* This cast gets only representation to cast to. For example:
|
||||
*
|
||||
* auto q1 = units::quantity_cast<int>(1ms);
|
||||
*
|
||||
* @tparam ToRep a representation type to use for a target quantity
|
||||
*/
|
||||
template<Scalar ToRep, typename D, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||
requires detail::basic_arithmetic<std::common_type_t<ToRep, Rep, intmax_t>>
|
||||
{
|
||||
return quantity_cast<quantity<U, ToRep>>(q);
|
||||
return quantity_cast<quantity<D, U, ToRep>>(q);
|
||||
}
|
||||
|
||||
// quantity_values
|
||||
|
||||
/**
|
||||
* @brief A type trait that defines zero, one, min, and max for a representation type
|
||||
*
|
||||
* The zero, one, min, and max member functions in units::quantity forward their work to
|
||||
* these methods. This type can be specialized if the representation Rep requires a specific
|
||||
* implementation to return these quantity objects.
|
||||
*
|
||||
* @tparam Rep a representation type for which a type trait is defined
|
||||
*/
|
||||
template<Scalar Rep>
|
||||
struct quantity_values {
|
||||
static constexpr Rep zero() noexcept { return Rep(0); }
|
||||
static constexpr Rep one() noexcept { return Rep(1); }
|
||||
static constexpr Rep max() noexcept { return std::numeric_limits<Rep>::max(); }
|
||||
static constexpr Rep min() noexcept { return std::numeric_limits<Rep>::lowest(); }
|
||||
static constexpr Rep max() noexcept { return std::numeric_limits<Rep>::max(); }
|
||||
};
|
||||
|
||||
|
||||
// quantity
|
||||
|
||||
template<Unit U, Scalar Rep = double>
|
||||
/**
|
||||
* @brief A quantity
|
||||
*
|
||||
* Property of a phenomenon, body, or substance, where the property has a magnitude that can be
|
||||
* expressed by means of a number and a measurement unit.
|
||||
*
|
||||
* @tparam D a dimension of the quantity (can be either a BaseDimension or a DerivedDimension)
|
||||
* @tparam U a measurement unit of the quantity
|
||||
* @tparam Rep a type to be used to represent values of a quantity
|
||||
*/
|
||||
template<Dimension D, UnitOf<D> U, Scalar Rep = double>
|
||||
class quantity {
|
||||
Rep value_;
|
||||
|
||||
public:
|
||||
using dimension = D;
|
||||
using unit = U;
|
||||
using rep = Rep;
|
||||
using dimension = U::dimension;
|
||||
|
||||
quantity() = default;
|
||||
quantity(const quantity&) = default;
|
||||
@@ -205,17 +261,13 @@ namespace units {
|
||||
|
||||
template<Scalar Value>
|
||||
requires detail::safe_convertible<Value, rep>
|
||||
constexpr explicit quantity(const Value& v): value_{static_cast<rep>(v)}
|
||||
{
|
||||
}
|
||||
constexpr explicit quantity(const Value& v) : value_{static_cast<rep>(v)} {}
|
||||
|
||||
template<Quantity Q2>
|
||||
requires same_dim<dimension, typename Q2::dimension> &&
|
||||
detail::safe_convertible<typename Q2::rep, rep> &&
|
||||
detail::safe_divisible<rep, typename Q2::unit, unit>
|
||||
constexpr quantity(const Q2& q): value_{quantity_cast<quantity>(q).count()}
|
||||
{
|
||||
}
|
||||
constexpr quantity(const Q2& q) : value_{quantity_cast<quantity>(q).count()} {}
|
||||
|
||||
quantity& operator=(const quantity&) = default;
|
||||
quantity& operator=(quantity&&) = default;
|
||||
@@ -277,7 +329,9 @@ namespace units {
|
||||
requires requires(T v) { { v++ } -> SAME_AS(T); }
|
||||
constexpr quantity operator++(int)
|
||||
// requires requires(rep v) { { v++ } -> std::same_as<rep>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
||||
{ return quantity(value_++); }
|
||||
{
|
||||
return quantity(value_++);
|
||||
}
|
||||
|
||||
template<typename T = Rep>
|
||||
requires requires(T v) { { --v } -> SAME_AS(T&); }
|
||||
@@ -292,7 +346,9 @@ namespace units {
|
||||
requires requires(T v) { { v-- } -> SAME_AS(T); }
|
||||
constexpr quantity operator--(int)
|
||||
// requires requires(rep v) { { v-- } -> std::same_as<rep>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
||||
{ return quantity(value_--); }
|
||||
{
|
||||
return quantity(value_--);
|
||||
}
|
||||
|
||||
template<typename T = Rep>
|
||||
requires requires(T v1, T v2) { { v1 += v2 } -> SAME_AS(T&); }
|
||||
@@ -354,184 +410,188 @@ namespace units {
|
||||
template<class CharT, class Traits>
|
||||
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const quantity& q)
|
||||
{
|
||||
return os << q.count() << " " << detail::unit_text<quantity::unit>();
|
||||
return os; // << q.count() << " " << detail::unit_text<quantity::unit>();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator+(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires same_dim<typename U1::dimension, typename U2::dimension> && detail::basic_arithmetic<Rep1, Rep2>
|
||||
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator+(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||
requires detail::basic_arithmetic<Rep1, Rep2>
|
||||
{
|
||||
using common_rep = decltype(lhs.count() + rhs.count());
|
||||
using ret = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>, common_rep>;
|
||||
using ret = common_quantity<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, common_rep>;
|
||||
return ret(ret(lhs).count() + ret(rhs).count());
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator-(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
||||
detail::basic_arithmetic<Rep1, Rep2>
|
||||
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator-(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||
requires detail::basic_arithmetic<Rep1, Rep2>
|
||||
{
|
||||
using common_rep = decltype(lhs.count() - rhs.count());
|
||||
using ret = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>, common_rep>;
|
||||
using ret = common_quantity<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, common_rep>;
|
||||
return ret(ret(lhs).count() - ret(rhs).count());
|
||||
}
|
||||
|
||||
template<typename U, typename Rep, Scalar Value>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator*(const quantity<U, Rep>& q, const Value& v)
|
||||
template<typename D, typename U, typename Rep, Scalar Value>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator*(const quantity<D, U, Rep>& q, const Value& v)
|
||||
requires std::magma<std::ranges::times, Rep, Value>
|
||||
{
|
||||
using common_rep = decltype(q.count() * v);
|
||||
using ret = quantity<U, common_rep>;
|
||||
using ret = quantity<D, U, common_rep>;
|
||||
return ret(q.count() * v);
|
||||
}
|
||||
|
||||
template<Scalar Value, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator*(const Value& v, const quantity<U, Rep>& q)
|
||||
template<Scalar Value, typename D, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator*(const Value& v, const quantity<D, U, Rep>& q)
|
||||
requires std::magma<std::ranges::times, Value, Rep>
|
||||
{
|
||||
return q * v;
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Scalar AUTO operator*(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires same_dim<typename U1::dimension, dim_invert<typename U2::dimension>> &&
|
||||
detail::basic_arithmetic<Rep1, Rep2>
|
||||
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Scalar AUTO operator*(const quantity<D1, U1, Rep1>& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||
requires same_dim<D1, dim_invert<D2>>&& detail::basic_arithmetic<Rep1, Rep2>
|
||||
{
|
||||
using common_rep = decltype(lhs.count() * rhs.count());
|
||||
using ratio = ratio_multiply<typename U1::ratio, typename U2::ratio>;
|
||||
return common_rep(lhs.count()) * common_rep(rhs.count()) * common_rep(ratio::num) / common_rep(ratio::den);
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator*(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires (!same_dim<typename U1::dimension, dim_invert<typename U2::dimension>>) &&
|
||||
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator*(const quantity<D1, U1, Rep1>& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||
requires (!same_dim<D1, dim_invert<D2>>) &&
|
||||
(treat_as_floating_point<decltype(lhs.count() * rhs.count())> ||
|
||||
(std::ratio_multiply<typename U1::ratio, typename U2::ratio>::den == 1)) &&
|
||||
detail::basic_arithmetic<Rep1, Rep2>
|
||||
{
|
||||
using dim = dimension_multiply<typename U1::dimension, typename U2::dimension>;
|
||||
using dim = dimension_multiply<D1, D2>;
|
||||
using ratio = ratio_multiply<typename U1::ratio, typename U2::ratio>;
|
||||
using unit = downcast<detail::reference_unit<typename dim::coherent_unit::reference, ratio>>;
|
||||
using common_rep = decltype(lhs.count() * rhs.count());
|
||||
using ret = quantity<downcast<unit<dim, ratio_multiply<typename U1::ratio, typename U2::ratio>>>, common_rep>;
|
||||
using ret = quantity<dim, unit, common_rep>;
|
||||
return ret(lhs.count() * rhs.count());
|
||||
}
|
||||
|
||||
template<Scalar Value, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator/(const Value& v, const quantity<U, Rep>& q)
|
||||
template<typename D, Scalar Value, typename U, typename Rep>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator/(const Value& v, const quantity<D, U, Rep>& q)
|
||||
requires std::magma<std::ranges::divided_by, Value, Rep>
|
||||
{
|
||||
Expects(q != std::remove_cvref_t<decltype(q)>(0));
|
||||
|
||||
using dim = dim_invert<typename U::dimension>;
|
||||
using dim = dim_invert<D>;
|
||||
using ratio = ratio<U::ratio::den, U::ratio::num>;
|
||||
using unit = downcast<detail::reference_unit<typename dim::coherent_unit::reference, ratio>>;
|
||||
using common_rep = decltype(v / q.count());
|
||||
using ret = quantity<downcast<unit<dim, ratio<U::ratio::den, U::ratio::num>>>, common_rep>;
|
||||
using ret = quantity<dim, unit, common_rep>;
|
||||
return ret(v / q.count());
|
||||
}
|
||||
|
||||
template<typename U, typename Rep, Scalar Value>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator/(const quantity<U, Rep>& q, const Value& v)
|
||||
template<typename D, typename U, typename Rep, Scalar Value>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator/(const quantity<D, U, Rep>& q, const Value& v)
|
||||
requires std::magma<std::ranges::divided_by, Rep, Value>
|
||||
{
|
||||
Expects(v != Value{0});
|
||||
|
||||
using common_rep = decltype(q.count() / v);
|
||||
using ret = quantity<U, common_rep>;
|
||||
using ret = quantity<D, U, common_rep>;
|
||||
return ret(q.count() / v);
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Scalar AUTO operator/(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
||||
detail::basic_arithmetic<Rep1, Rep2>
|
||||
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Scalar AUTO operator/(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||
requires detail::basic_arithmetic<Rep1, Rep2>
|
||||
{
|
||||
Expects(rhs != std::remove_cvref_t<decltype(rhs)>(0));
|
||||
|
||||
using common_rep = decltype(lhs.count() / rhs.count());
|
||||
using cq = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>, common_rep>;
|
||||
using cq = common_quantity<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, common_rep>;
|
||||
return cq(lhs).count() / cq(rhs).count();
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator/(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires (!same_dim<typename U1::dimension, typename U2::dimension>) &&
|
||||
(treat_as_floating_point<decltype(lhs.count() / rhs.count())> ||
|
||||
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator/(const quantity<D1, U1, Rep1>& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||
requires (treat_as_floating_point<decltype(lhs.count() / rhs.count())> ||
|
||||
(ratio_divide<typename U1::ratio, typename U2::ratio>::den == 1)) &&
|
||||
detail::basic_arithmetic<Rep1, Rep2>
|
||||
{
|
||||
Expects(rhs != std::remove_cvref_t<decltype(rhs)>(0));
|
||||
|
||||
using common_rep = decltype(lhs.count() / rhs.count());
|
||||
using dim = dimension_divide<typename U1::dimension, typename U2::dimension>;
|
||||
using ret = quantity<downcast<unit<dim, ratio_divide<typename U1::ratio, typename U2::ratio>>>, common_rep>;
|
||||
using dim = dimension_divide<D1, D2>;
|
||||
using unit = downcast<detail::reference_unit<typename dim::coherent_unit::reference,
|
||||
ratio_divide<typename U1::ratio, typename U2::ratio>>>;
|
||||
using ret = quantity<dim, unit, common_rep>;
|
||||
return ret(lhs.count() / rhs.count());
|
||||
}
|
||||
|
||||
template<typename U, typename Rep, Scalar Value>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator%(const quantity<U, Rep>& q, const Value& v)
|
||||
requires (!treat_as_floating_point<Rep>) && (!treat_as_floating_point<Value>) &&
|
||||
template<typename D, typename U, typename Rep, Scalar Value>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator%(const quantity<D, U, Rep>& q, const Value& v)
|
||||
requires (!treat_as_floating_point<Rep>) &&
|
||||
(!treat_as_floating_point<Value>) &&
|
||||
std::magma<std::ranges::modulus, Rep, Value>
|
||||
{
|
||||
using common_rep = decltype(q.count() % v);
|
||||
using ret = quantity<U, common_rep>;
|
||||
using ret = quantity<D, U, common_rep>;
|
||||
return ret(q.count() % v);
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator%(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires (!treat_as_floating_point<Rep1>) && (!treat_as_floating_point<Rep2>) &&
|
||||
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr Quantity AUTO operator%(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||
requires (!treat_as_floating_point<Rep1>) &&
|
||||
(!treat_as_floating_point<Rep2>) &&
|
||||
std::magma<std::ranges::modulus, Rep1, Rep2>
|
||||
{
|
||||
using common_rep = decltype(lhs.count() % rhs.count());
|
||||
using ret = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>, common_rep>;
|
||||
using ret = common_quantity<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>, common_rep>;
|
||||
return ret(ret(lhs).count() % ret(rhs).count());
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator==(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
||||
detail::basic_arithmetic<Rep1, Rep2> && std::equality_comparable_with<Rep1, Rep2>
|
||||
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator==(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||
requires detail::basic_arithmetic<Rep1, Rep2> &&
|
||||
std::equality_comparable_with<Rep1, Rep2>
|
||||
{
|
||||
using cq = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>>;
|
||||
using cq = common_quantity<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>>;
|
||||
return cq(lhs).count() == cq(rhs).count();
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator!=(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
||||
detail::basic_arithmetic<Rep1, Rep2> && std::equality_comparable_with<Rep1, Rep2>
|
||||
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator!=(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||
requires detail::basic_arithmetic<Rep1, Rep2> &&
|
||||
std::equality_comparable_with<Rep1, Rep2>
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator<(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
||||
detail::basic_arithmetic<Rep1, Rep2> && std::totally_ordered_with<Rep1, Rep2>
|
||||
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator<(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||
requires detail::basic_arithmetic<Rep1, Rep2> &&
|
||||
std::totally_ordered_with<Rep1, Rep2>
|
||||
{
|
||||
using cq = common_quantity<quantity<U1, Rep1>, quantity<U2, Rep2>>;
|
||||
using cq = common_quantity<quantity<D, U1, Rep1>, quantity<D, U2, Rep2>>;
|
||||
return cq(lhs).count() < cq(rhs).count();
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator<=(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
||||
detail::basic_arithmetic<Rep1, Rep2> && std::totally_ordered_with<Rep1, Rep2>
|
||||
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator<=(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||
requires detail::basic_arithmetic<Rep1, Rep2> &&
|
||||
std::totally_ordered_with<Rep1, Rep2>
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator>(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
||||
detail::basic_arithmetic<Rep1, Rep2> && std::totally_ordered_with<Rep1, Rep2>
|
||||
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator>(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||
requires detail::basic_arithmetic<Rep1, Rep2> &&
|
||||
std::totally_ordered_with<Rep1, Rep2>
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator>=(const quantity<U1, Rep1>& lhs, const quantity<U2, Rep2>& rhs)
|
||||
requires same_dim<typename U1::dimension, typename U2::dimension> &&
|
||||
detail::basic_arithmetic<Rep1, Rep2> && std::totally_ordered_with<Rep1, Rep2>
|
||||
template<typename D, typename U1, typename Rep1, typename U2, typename Rep2>
|
||||
[[nodiscard]] constexpr bool operator>=(const quantity<D, U1, Rep1>& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||
requires detail::basic_arithmetic<Rep1, Rep2> &&
|
||||
std::totally_ordered_with<Rep1, Rep2>
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
@@ -42,6 +42,13 @@ struct reference_unit : downcast_base<reference_unit<U, R>> {
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// UnitOf
|
||||
template<typename U, typename D>
|
||||
concept UnitOf =
|
||||
Unit<U> &&
|
||||
Dimension<D> &&
|
||||
std::same_as<typename U::reference, typename D::coherent_unit::reference>;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// same_reference_units
|
||||
@@ -49,8 +56,7 @@ template<DerivedDimension D, Unit... Us>
|
||||
inline constexpr bool same_reference_units = false;
|
||||
|
||||
template<typename... Es, Unit... Us>
|
||||
inline constexpr bool same_reference_units<derived_dimension<Es...>, Us...> =
|
||||
(std::same_as<typename Es::dimension::coherent_unit::reference, typename Us::reference> && ...);
|
||||
inline constexpr bool same_reference_units<derived_dimension<Es...>, Us...> = (UnitOf<Us, typename Es::dimension> && ...);
|
||||
|
||||
// deduced_unit
|
||||
template<typename Result, int UnitExpNum, int UnitExpDen, typename UnitRatio>
|
||||
|
@@ -27,7 +27,7 @@ add_library(unit_tests_static
|
||||
# fixed_string_test.cpp
|
||||
# math_test.cpp
|
||||
# new_design.cpp
|
||||
# quantity_test.cpp
|
||||
quantity_test.cpp
|
||||
ratio_test.cpp
|
||||
# si_test.cpp
|
||||
type_list_test.cpp
|
||||
|
@@ -20,12 +20,12 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "units/dimensions/velocity.h"
|
||||
#include "units/dimensions/frequency.h"
|
||||
#include "units/dimensions/area.h"
|
||||
#include "units/math.h"
|
||||
#include <utility>
|
||||
#include "units/physical/si/area.h"
|
||||
#include "units/physical/si/frequency.h"
|
||||
#include "units/physical/si/velocity.h"
|
||||
#include <chrono>
|
||||
#include <utility>
|
||||
|
||||
using namespace units;
|
||||
|
||||
@@ -34,15 +34,30 @@ namespace {
|
||||
template<typename T>
|
||||
class my_value {
|
||||
T value_{};
|
||||
|
||||
public:
|
||||
my_value() = default;
|
||||
constexpr my_value(T v) : value_(std::move(v)) {}
|
||||
|
||||
// constexpr my_value& operator+=(my_value other) { value_ += other.value_; return *this; }
|
||||
// constexpr my_value& operator-=(my_value other) { value_ -= other.value_; return *this; }
|
||||
// constexpr my_value& operator*=(my_value other) { value_ *= other.value_; return *this; }
|
||||
// constexpr my_value& operator/=(my_value other) { value_ /= other.value_; return *this; }
|
||||
|
||||
[[nodiscard]] constexpr my_value operator-() const { return my_value(-value_); }
|
||||
|
||||
[[nodiscard]] friend constexpr my_value operator+(my_value lhs, my_value rhs) { return my_value(lhs.value_ + rhs.value_); }
|
||||
[[nodiscard]] friend constexpr my_value operator-(my_value lhs, my_value rhs) { return my_value(lhs.value_ - rhs.value_); }
|
||||
[[nodiscard]] friend constexpr my_value operator*(my_value lhs, my_value rhs) { return my_value(lhs.value_ * rhs.value_); }
|
||||
[[nodiscard]] friend constexpr my_value operator/(my_value lhs, my_value rhs) { return my_value(lhs.value_ / rhs.value_); }
|
||||
[[nodiscard]] friend constexpr my_value operator+(my_value lhs, my_value rhs) {
|
||||
return my_value(lhs.value_ + rhs.value_);
|
||||
}
|
||||
[[nodiscard]] friend constexpr my_value operator-(my_value lhs, my_value rhs) {
|
||||
return my_value(lhs.value_ - rhs.value_);
|
||||
}
|
||||
[[nodiscard]] friend constexpr my_value operator*(my_value lhs, my_value rhs) {
|
||||
return my_value(lhs.value_ * rhs.value_);
|
||||
}
|
||||
[[nodiscard]] friend constexpr my_value operator/(my_value lhs, my_value rhs) {
|
||||
return my_value(lhs.value_ / rhs.value_);
|
||||
}
|
||||
|
||||
[[nodiscard]] friend constexpr bool operator==(my_value lhs, my_value rhs) { return lhs.value_ == rhs.value_; }
|
||||
[[nodiscard]] friend constexpr bool operator!=(my_value lhs, my_value rhs) { return !(lhs == rhs); }
|
||||
@@ -73,16 +88,13 @@ namespace units {
|
||||
namespace std {
|
||||
|
||||
template<typename T, typename U>
|
||||
struct common_type<my_value<T>, my_value<U>> : std::type_identity<my_value<common_type_t<T, U>>> {
|
||||
};
|
||||
struct common_type<my_value<T>, my_value<U>> : std::type_identity<my_value<common_type_t<T, U>>> {};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct common_type<my_value<T>, U> : common_type<T, U> {
|
||||
};
|
||||
struct common_type<my_value<T>, U> : common_type<T, U> {};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct common_type<T, my_value<U>> : common_type<T, U> {
|
||||
};
|
||||
struct common_type<T, my_value<U>> : common_type<T, U> {};
|
||||
|
||||
} // namespace std
|
||||
|
||||
@@ -93,82 +105,84 @@ namespace {
|
||||
static_assert(std::convertible_to<float, my_value<float>>);
|
||||
|
||||
using namespace units;
|
||||
using namespace units::si;
|
||||
|
||||
// class invariants
|
||||
|
||||
// constexpr quantity<length, second, int> q; // should a static_assert
|
||||
// constexpr quantity<dim_length, metre, int> q(1); // should not compile
|
||||
// constexpr quantity<length, metre, quantity<metre, int>> error(0m); // should trigger a static_assert
|
||||
// constexpr quantity<int, int, double> error(0); // should trigger a static_assert
|
||||
// constexpr quantity<length, unit<length, std::ratio<-1, 1>>, int> error(0); // should trigger a static_assert
|
||||
|
||||
// member types
|
||||
|
||||
static_assert(std::is_same_v<quantity<metre, int>::rep, int>);
|
||||
static_assert(std::is_same_v<quantity<metre, double>::rep, double>);
|
||||
static_assert(std::is_same_v<quantity<metre, int>::unit, metre>);
|
||||
static_assert(std::is_same_v<quantity<kilometre, int>::unit, kilometre>);
|
||||
static_assert(std::is_same_v<length<metre, int>::rep, int>);
|
||||
static_assert(std::is_same_v<length<metre, double>::rep, double>);
|
||||
static_assert(std::is_same_v<length<metre, int>::unit, metre>);
|
||||
static_assert(std::is_same_v<length<kilometre, int>::unit, kilometre>);
|
||||
|
||||
// constructors
|
||||
|
||||
using my_int = my_value<int>;
|
||||
using my_double = my_value<double>;
|
||||
|
||||
static_assert(quantity<metre, int>().count() == 0);
|
||||
constexpr quantity<metre, int> km{1000};
|
||||
static_assert(length<metre, int>().count() == 0);
|
||||
constexpr length<metre, int> km{1000};
|
||||
static_assert(km.count() == 1000);
|
||||
static_assert(quantity<metre, int>(km).count() == km.count());
|
||||
static_assert(length<metre, int>(km).count() == km.count());
|
||||
|
||||
static_assert(quantity<metre, int>(1).count() == 1);
|
||||
static_assert(quantity<metre, int>(my_value(1)).count() == 1);
|
||||
static_assert(quantity<metre, my_int>(1).count() == my_int{1});
|
||||
// static_assert(quantity<metre, int>(1.0).count() == 1); // should not compile
|
||||
// static_assert(quantity<metre, int>(my_value(1.0)).count() == 1); // should not compile
|
||||
// static_assert(quantity<metre, my_value>(1.0).count() == 1); // should not compile
|
||||
static_assert(quantity<metre, double>(1.0).count() == 1.0);
|
||||
static_assert(quantity<metre, double>(my_value(1.0)).count() == 1.0);
|
||||
static_assert(quantity<metre, double>(1).count() == 1.0);
|
||||
static_assert(quantity<metre, double>(my_value(1)).count() == 1.0);
|
||||
static_assert(quantity<metre, double>(3.14).count() == 3.14);
|
||||
static_assert(quantity<metre, my_double>(1.0).count() == my_double{1.0});
|
||||
static_assert(quantity<metre, my_double>(1).count() == my_double{1.0});
|
||||
static_assert(quantity<metre, my_double>(3.14).count() == my_double{3.14});
|
||||
static_assert(length<metre, int>(1).count() == 1);
|
||||
static_assert(length<metre, int>(my_value(1)).count() == 1);
|
||||
static_assert(length<metre, my_int>(1).count() == my_int{1});
|
||||
// static_assert(length<metre, int>(1.0).count() == 1); // should not compile
|
||||
// static_assert(length<metre, int>(my_value(1.0)).count() == 1); // should not compile
|
||||
// static_assert(length<metre, my_value>(1.0).count() == 1); // should not compile
|
||||
static_assert(length<metre, double>(1.0).count() == 1.0);
|
||||
static_assert(length<metre, double>(my_value(1.0)).count() == 1.0);
|
||||
static_assert(length<metre, double>(1).count() == 1.0);
|
||||
static_assert(length<metre, double>(my_value(1)).count() == 1.0);
|
||||
static_assert(length<metre, double>(3.14).count() == 3.14);
|
||||
static_assert(length<metre, my_double>(1.0).count() == my_double{1.0});
|
||||
static_assert(length<metre, my_double>(1).count() == my_double{1.0});
|
||||
static_assert(length<metre, my_double>(3.14).count() == my_double{3.14});
|
||||
|
||||
static_assert(quantity<metre, int>(km).count() == 1000);
|
||||
// static_assert(quantity<metre, int>(quantity<metre, double>(3.14)).count() == 3); // should not compile
|
||||
static_assert(quantity<metre, int>(quantity_cast<quantity<metre, my_int>>(3.14m)).count() == 3);
|
||||
// static_assert(quantity<metre, int>(quantity<metre, my_double>(1000.0)).count() == 1000); // should not compile
|
||||
// static_assert(quantity<metre, my_value>(1000.0m).count() == 1000); // should not compile
|
||||
static_assert(quantity<metre, double>(1000.0m).count() == 1000.0);
|
||||
static_assert(quantity<metre, double>(quantity<metre, my_double>(1000.0)).count() == 1000.0);
|
||||
static_assert(quantity<metre, my_double>(1000.0m).count() == my_double{1000.0});
|
||||
static_assert(quantity<metre, double>(km).count() == 1000.0);
|
||||
static_assert(quantity<metre, my_double>(km).count() == my_double{1000.0});
|
||||
static_assert(quantity<metre, int>(1km).count() == 1000);
|
||||
// static_assert(quantity<metre, int>(1_s).count() == 1); // should not compile
|
||||
// static_assert(quantity<kilometre, int>(1010m).count() == 1); // should not compile
|
||||
static_assert(quantity<kilometre, int>(quantity_cast<quantity<kilometre, my_int>>(1010m)).count() == 1);
|
||||
static_assert(length<metre, int>(km).count() == 1000);
|
||||
// static_assert(length<metre, int>(length<metre, double>(3.14)).count() == 3); // should not compile
|
||||
static_assert(length<metre, int>(quantity_cast<length<metre, my_int>>(3.14m)).count() == 3);
|
||||
// static_assert(length<metre, int>(length<metre, my_double>(1000.0)).count() == 1000); // should not compile
|
||||
// static_assert(length<metre, my_value>(1000.0m).count() == 1000); // should not compile
|
||||
static_assert(length<metre, double>(1000.0m).count() == 1000.0);
|
||||
static_assert(length<metre, double>(length<metre, my_double>(1000.0)).count() == 1000.0);
|
||||
static_assert(length<metre, my_double>(1000.0m).count() == my_double{1000.0});
|
||||
static_assert(length<metre, double>(km).count() == 1000.0);
|
||||
static_assert(length<metre, my_double>(km).count() == my_double{1000.0});
|
||||
static_assert(length<metre, int>(1km).count() == 1000);
|
||||
// static_assert(length<metre, int>(1_s).count() == 1); // should not compile
|
||||
// static_assert(length<kilometre, int>(1010m).count() == 1); // should not compile
|
||||
static_assert(length<kilometre, int>(quantity_cast<length<kilometre, my_int>>(1010m)).count() == 1);
|
||||
|
||||
// assignment operator
|
||||
|
||||
static_assert([]() {
|
||||
quantity<metre, int> l1(1), l2(2);
|
||||
length<metre, int> l1(1), l2(2);
|
||||
return l2 = l1;
|
||||
}().count() == 1);
|
||||
}()
|
||||
.count() == 1);
|
||||
|
||||
// static member functions
|
||||
|
||||
static_assert(quantity<metre, int>::zero().count() == 0);
|
||||
static_assert(quantity<metre, int>::min().count() == std::numeric_limits<int>::lowest());
|
||||
static_assert(quantity<metre, int>::max().count() == std::numeric_limits<int>::max());
|
||||
static_assert(quantity<metre, double>::zero().count() == 0.0);
|
||||
static_assert(quantity<metre, double>::min().count() == std::numeric_limits<double>::lowest());
|
||||
static_assert(quantity<metre, double>::max().count() == std::numeric_limits<double>::max());
|
||||
static_assert(quantity<metre, my_int>::zero().count() == my_int{0});
|
||||
static_assert(quantity<metre, my_int>::min().count() == my_int{std::numeric_limits<int>::lowest()});
|
||||
static_assert(quantity<metre, my_int>::max().count() == my_int{std::numeric_limits<int>::max()});
|
||||
static_assert(quantity<metre, my_double>::zero().count() == my_double{0.0});
|
||||
static_assert(quantity<metre, my_double>::min().count() == my_double{std::numeric_limits<double>::lowest()});
|
||||
static_assert(quantity<metre, my_double>::max().count() == my_double{std::numeric_limits<double>::max()});
|
||||
static_assert(length<metre, int>::zero().count() == 0);
|
||||
static_assert(length<metre, int>::min().count() == std::numeric_limits<int>::lowest());
|
||||
static_assert(length<metre, int>::max().count() == std::numeric_limits<int>::max());
|
||||
static_assert(length<metre, double>::zero().count() == 0.0);
|
||||
static_assert(length<metre, double>::min().count() == std::numeric_limits<double>::lowest());
|
||||
static_assert(length<metre, double>::max().count() == std::numeric_limits<double>::max());
|
||||
static_assert(length<metre, my_int>::zero().count() == my_int{0});
|
||||
static_assert(length<metre, my_int>::min().count() == my_int{std::numeric_limits<int>::lowest()});
|
||||
static_assert(length<metre, my_int>::max().count() == my_int{std::numeric_limits<int>::max()});
|
||||
static_assert(length<metre, my_double>::zero().count() == my_double{0.0});
|
||||
static_assert(length<metre, my_double>::min().count() == my_double{std::numeric_limits<double>::lowest()});
|
||||
static_assert(length<metre, my_double>::max().count() == my_double{std::numeric_limits<double>::max()});
|
||||
|
||||
// unary member operators
|
||||
|
||||
@@ -182,19 +196,19 @@ namespace {
|
||||
static_assert([](auto v) {
|
||||
auto vv = v++;
|
||||
return std::make_pair(v, vv);
|
||||
}(km) == std::make_pair(quantity<metre, int>(1001), quantity<metre, int>(1000)));
|
||||
}(km) == std::make_pair(length<metre, int>(1001), length<metre, int>(1000)));
|
||||
static_assert([](auto v) {
|
||||
auto vv = ++v;
|
||||
return std::make_pair(v, vv);
|
||||
}(km) == std::make_pair(quantity<metre, int>(1001), quantity<metre, int>(1001)));
|
||||
}(km) == std::make_pair(length<metre, int>(1001), length<metre, int>(1001)));
|
||||
static_assert([](auto v) {
|
||||
auto vv = v--;
|
||||
return std::make_pair(v, vv);
|
||||
}(km) == std::make_pair(quantity<metre, int>(999), quantity<metre, int>(1000)));
|
||||
}(km) == std::make_pair(length<metre, int>(999), length<metre, int>(1000)));
|
||||
static_assert([](auto v) {
|
||||
auto vv = --v;
|
||||
return std::make_pair(v, vv);
|
||||
}(km) == std::make_pair(quantity<metre, int>(999), quantity<metre, int>(999)));
|
||||
}(km) == std::make_pair(length<metre, int>(999), length<metre, int>(999)));
|
||||
|
||||
// compound assignment
|
||||
|
||||
@@ -214,21 +228,26 @@ namespace {
|
||||
|
||||
// non-member arithmetic operators
|
||||
|
||||
static_assert(std::is_same_v<decltype(quantity<metre, int>() + quantity<metre, double>()), quantity<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(quantity<metre, int>() + quantity<metre, double>()), quantity<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(quantity<kilometre, int>() + quantity<metre, double>()), quantity<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(quantity<metre, double>() - quantity<metre, int>()), quantity<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(quantity<kilometre, double>() - quantity<metre, int>()), quantity<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(quantity<metre, int>() * 1.0), quantity<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(1.0 * quantity<metre, int>()), quantity<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(quantity<metre_per_second, int>() * quantity<second, int>()), quantity<metre, int>>);
|
||||
static_assert(std::is_same_v<decltype(1 / quantity<second, int>()), quantity<hertz, int>>);
|
||||
static_assert(std::is_same_v<decltype(quantity<metre, int>() / 1.0), quantity<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(quantity<metre, int>() / quantity<metre, double>()), double>);
|
||||
static_assert(std::is_same_v<decltype(quantity<kilometre, int>() / quantity<metre, double>()), double>);
|
||||
static_assert(std::is_same_v<decltype(quantity<metre, int>() / quantity<second, int>()), quantity<metre_per_second, int>>);
|
||||
static_assert(std::is_same_v<decltype(quantity<metre, int>() % short(1)), quantity<metre, int>>);
|
||||
static_assert(std::is_same_v<decltype(quantity<metre, int>() % quantity<metre, short>(1)), quantity<metre, int>>);
|
||||
static_assert(std::is_same_v<decltype(length<metre, int>() + length<metre, double>()), length<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(length<metre, int>() + length<metre, double>()), length<metre, double>>);
|
||||
static_assert(
|
||||
std::is_same_v<decltype(length<kilometre, int>() + length<metre, double>()), length<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(length<metre, double>() - length<metre, int>()), length<metre, double>>);
|
||||
static_assert(
|
||||
std::is_same_v<decltype(length<kilometre, double>() - length<metre, int>()), length<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(length<metre, int>() * 1.0), length<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(1.0 * length<metre, int>()), length<metre, double>>);
|
||||
static_assert(
|
||||
std::is_same_v<decltype(velocity<metre_per_second, int>() * si::time<second, int>()), length<metre, int>>);
|
||||
static_assert(std::is_same_v<decltype(1 / si::time<second, int>()), frequency<hertz, int>>);
|
||||
static_assert(std::is_same_v<decltype(1 / frequency<hertz, int>()), si::time<second, int>>);
|
||||
static_assert(std::is_same_v<decltype(length<metre, int>() / 1.0), length<metre, double>>);
|
||||
static_assert(std::is_same_v<decltype(length<metre, int>() / length<metre, double>()), double>);
|
||||
static_assert(std::is_same_v<decltype(length<kilometre, int>() / length<metre, double>()), double>);
|
||||
static_assert(
|
||||
std::is_same_v<decltype(length<metre, int>() / si::time<second, int>()), velocity<metre_per_second, int>>);
|
||||
static_assert(std::is_same_v<decltype(length<metre, int>() % short(1)), length<metre, int>>);
|
||||
static_assert(std::is_same_v<decltype(length<metre, int>() % length<metre, short>(1)), length<metre, int>>);
|
||||
|
||||
static_assert((1m + km).count() == 1001);
|
||||
static_assert((1m + 1km).count() == 1001);
|
||||
@@ -276,22 +295,23 @@ namespace {
|
||||
|
||||
// is_quantity
|
||||
|
||||
static_assert(Quantity<quantity<millimetre, int>>);
|
||||
static_assert(Quantity<length<millimetre, int>>);
|
||||
|
||||
// common_quantity
|
||||
|
||||
static_assert(std::is_same_v<common_quantity<quantity<metre, int>, quantity<kilometre, int>>, quantity<metre, int>>);
|
||||
static_assert(std::is_same_v<common_quantity<quantity<kilometre, long long>, quantity<metre, int>>, quantity<metre, long long>>);
|
||||
static_assert(std::is_same_v<common_quantity<quantity<kilometre, long long>, quantity<millimetre, double>>, quantity<millimetre, double>>);
|
||||
static_assert(std::is_same_v<common_quantity<length<metre, int>, length<kilometre, int>>, length<metre, int>>);
|
||||
static_assert(
|
||||
std::is_same_v<common_quantity<length<kilometre, long long>, length<metre, int>>, length<metre, long long>>);
|
||||
static_assert(std::is_same_v<common_quantity<length<kilometre, long long>, length<millimetre, double>>,
|
||||
length<millimetre, double>>);
|
||||
|
||||
// quantity_cast
|
||||
|
||||
static_assert(std::is_same_v<decltype(quantity_cast<unit<length, ratio<1>>>(2km))::unit, metre>);
|
||||
static_assert(std::is_same_v<decltype(quantity_cast<unit<dimension<units::exp<base_dim_length, 1>>, ratio<1>>>(2km))::unit, metre>);
|
||||
static_assert(std::is_same_v<decltype(quantity_cast<detail::reference_unit<metre, ratio<1>>>(2km))::unit, metre>);
|
||||
|
||||
// static_assert(quantity_cast<int>(2km).count() == 2000); // should not compile
|
||||
static_assert(quantity_cast<quantity<metre, int>>(2km).count() == 2000);
|
||||
static_assert(quantity_cast<quantity<kilometre, int>>(2000m).count() == 2);
|
||||
static_assert(quantity_cast<length<metre, int>>(2km).count() == 2000);
|
||||
static_assert(quantity_cast<length<kilometre, int>>(2000m).count() == 2);
|
||||
|
||||
// time
|
||||
|
||||
|
Reference in New Issue
Block a user