mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-30 18:37:15 +02:00
refactor: got rid of gcc-9 backlog
BREAKING CHANGE: gcc-9.3 no longer supported
This commit is contained in:
@ -25,5 +25,4 @@ Until then, please code alike what is there already:
|
|||||||
|
|
||||||
## Backward Compatibility
|
## Backward Compatibility
|
||||||
|
|
||||||
Before submission, please remember to check if the code compiles fine on all the supported compilers (especially gcc-9.3 and MSVC are tricky).
|
Before submission, please remember to check if the code compiles fine on all the supported compilers (gcc-10 and MSVC so far).
|
||||||
Unfortunately, we cannot add gcc-9.3 to the CI process as it is [not supported by Conan Docker images](https://github.com/conan-io/conan-docker-tools/issues/200).
|
|
||||||
|
13
conanfile.py
13
conanfile.py
@ -66,8 +66,8 @@ class UnitsConan(ConanFile):
|
|||||||
compiler = self.settings.compiler
|
compiler = self.settings.compiler
|
||||||
version = Version(self.settings.compiler.version)
|
version = Version(self.settings.compiler.version)
|
||||||
if compiler == "gcc":
|
if compiler == "gcc":
|
||||||
if version < "9.3":
|
if version < "10.0":
|
||||||
raise ConanInvalidConfiguration("mp-units requires at least g++-9.3")
|
raise ConanInvalidConfiguration("mp-units requires at least g++-10")
|
||||||
elif compiler == "Visual Studio":
|
elif compiler == "Visual Studio":
|
||||||
if version < "16":
|
if version < "16":
|
||||||
raise ConanInvalidConfiguration("mp-units requires at least MSVC 16")
|
raise ConanInvalidConfiguration("mp-units requires at least MSVC 16")
|
||||||
@ -88,11 +88,6 @@ class UnitsConan(ConanFile):
|
|||||||
def configure(self):
|
def configure(self):
|
||||||
self._validate_compiler_settings()
|
self._validate_compiler_settings()
|
||||||
|
|
||||||
def requirements(self):
|
|
||||||
if ((self.settings.compiler == "gcc" and Version(self.settings.compiler.version) < "10") or
|
|
||||||
self.settings.compiler == "clang"):
|
|
||||||
self.requires("range-v3/0.11.0")
|
|
||||||
|
|
||||||
def build_requirements(self):
|
def build_requirements(self):
|
||||||
if self._run_tests:
|
if self._run_tests:
|
||||||
self.build_requires("catch2/2.13.0")
|
self.build_requires("catch2/2.13.0")
|
||||||
@ -123,10 +118,6 @@ class UnitsConan(ConanFile):
|
|||||||
"-Wno-literal-suffix",
|
"-Wno-literal-suffix",
|
||||||
"-Wno-non-template-friend",
|
"-Wno-non-template-friend",
|
||||||
]
|
]
|
||||||
if version < "10":
|
|
||||||
self.cpp_info.cxxflags.extend([
|
|
||||||
"-fconcepts"
|
|
||||||
])
|
|
||||||
elif compiler == "Visual Studio":
|
elif compiler == "Visual Studio":
|
||||||
self.cpp_info.cxxflags = [
|
self.cpp_info.cxxflags = [
|
||||||
"/utf-8",
|
"/utf-8",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Release notes
|
# Release notes
|
||||||
|
|
||||||
- **0.6.0 WIP**
|
- **0.6.0 WIP**
|
||||||
- Minimum compiler version supported changed to gcc-9.3
|
- gcc-9 is no longer supported (at least gcc-10 is required)
|
||||||
- MSVC 16.7 support added
|
- MSVC 16.7 support added
|
||||||
- linear_algebra updated to 0.7.0/stable
|
- linear_algebra updated to 0.7.0/stable
|
||||||
- fmt updated to 7.0.3
|
- fmt updated to 7.0.3
|
||||||
|
@ -44,7 +44,7 @@ a few additional member types and functions::
|
|||||||
|
|
||||||
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
template<typename D1, typename U1, typename Rep1, typename D2, typename U2, typename Rep2>
|
||||||
requires detail::basic_arithmetic<Rep1, Rep2> && (!equivalent_dim<D1, D2>)
|
requires detail::basic_arithmetic<Rep1, Rep2> && (!equivalent_dim<D1, D2>)
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator/(const quantity<D1, U1, Rep1>& lhs,
|
[[nodiscard]] constexpr Quantity auto operator/(const quantity<D1, U1, Rep1>& lhs,
|
||||||
const quantity<D2, U2, Rep2>& rhs);
|
const quantity<D2, U2, Rep2>& rhs);
|
||||||
|
|
||||||
Additional functions provide the support for operations that result in a
|
Additional functions provide the support for operations that result in a
|
||||||
|
@ -16,7 +16,7 @@ with a permissive `MIT license <https://github.com/mpusz/units/blob/master/LICEN
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
As this library targets C++23 and extensively uses C++20 features as of now it compiles correctly
|
As this library targets C++23 and extensively uses C++20 features as of now it compiles correctly
|
||||||
only with gcc-9.3, MSVC 16.7, and newer.
|
only with gcc-10, MSVC 16.7, and newer.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
@ -4,7 +4,7 @@ Usage
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
This library targets C++23 and extensively uses C++20 features that is why, as of now, it compiles correctly
|
This library targets C++23 and extensively uses C++20 features that is why, as of now, it compiles correctly
|
||||||
only with gcc-9.3, MSVC 16.7, and newer.
|
only with gcc-10, MSVC 16.7, and newer.
|
||||||
|
|
||||||
Repository Structure and Dependencies
|
Repository Structure and Dependencies
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
@ -17,8 +17,6 @@ This repository contains three independent CMake-based projects:
|
|||||||
- when this library will become part of the C++ standard it will have no external dependencies
|
- when this library will become part of the C++ standard it will have no external dependencies
|
||||||
but until then it depends on:
|
but until then it depends on:
|
||||||
|
|
||||||
- `range-v3 <https://github.com/ericniebler/range-v3>`_ (only for gcc versions < 10.0) to provide
|
|
||||||
C++20 concepts library definitions.
|
|
||||||
- `{fmt} <https://github.com/fmtlib/fmt>`_ to provide text formatting of quantities.
|
- `{fmt} <https://github.com/fmtlib/fmt>`_ to provide text formatting of quantities.
|
||||||
- `ms-gsl <https://github.com/microsoft/GSL>`_ to verify runtime contracts with `Expects` macro.
|
- `ms-gsl <https://github.com/microsoft/GSL>`_ to verify runtime contracts with `Expects` macro.
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <units/physical/si/prefixes.h>
|
#include <units/physical/si/prefixes.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
// get at the units text of the quantity, without its numeric value
|
// get at the units text of the quantity, without its numeric value
|
||||||
inline auto constexpr units_str(const units::Quantity AUTO& q)
|
inline auto constexpr units_str(const units::Quantity auto& q)
|
||||||
{
|
{
|
||||||
typedef std::remove_cvref_t<decltype(q)> qtype;
|
typedef std::remove_cvref_t<decltype(q)> qtype;
|
||||||
return units::detail::unit_text<typename qtype::dimension, typename qtype::unit>();
|
return units::detail::unit_text<typename qtype::dimension, typename qtype::unit>();
|
||||||
|
@ -44,13 +44,13 @@ fixed_double_si_avg_speed(si::length<si::metre> d,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename U1, typename R1, typename U2, typename R2>
|
template<typename U1, typename R1, typename U2, typename R2>
|
||||||
constexpr Speed AUTO si_avg_speed(si::length<U1, R1> d,
|
constexpr Speed auto si_avg_speed(si::length<U1, R1> d,
|
||||||
si::time<U2, R2> t)
|
si::time<U2, R2> t)
|
||||||
{
|
{
|
||||||
return d / t;
|
return d / t;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Speed AUTO avg_speed(Length AUTO d, Time AUTO t)
|
constexpr Speed auto avg_speed(Length auto d, Time auto t)
|
||||||
{
|
{
|
||||||
return d / t;
|
return d / t;
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ void example()
|
|||||||
// SI (int)
|
// SI (int)
|
||||||
{
|
{
|
||||||
using namespace units::physical::si::literals;
|
using namespace units::physical::si::literals;
|
||||||
constexpr Length AUTO distance = 220q_km; // constructed from a UDL
|
constexpr Length auto distance = 220q_km; // constructed from a UDL
|
||||||
constexpr si::time<si::hour, int> duration(2); // constructed from a value
|
constexpr si::time<si::hour, int> duration(2); // constructed from a value
|
||||||
|
|
||||||
std::cout << "SI units with 'int' as representation\n";
|
std::cout << "SI units with 'int' as representation\n";
|
||||||
@ -82,7 +82,7 @@ void example()
|
|||||||
// SI (double)
|
// SI (double)
|
||||||
{
|
{
|
||||||
using namespace units::physical::si::literals;
|
using namespace units::physical::si::literals;
|
||||||
constexpr Length AUTO distance = 220.q_km; // constructed from a UDL
|
constexpr Length auto distance = 220.q_km; // constructed from a UDL
|
||||||
constexpr si::time<si::hour> duration(2); // constructed from a value
|
constexpr si::time<si::hour> duration(2); // constructed from a value
|
||||||
|
|
||||||
std::cout << "\nSI units with 'double' as representation\n";
|
std::cout << "\nSI units with 'double' as representation\n";
|
||||||
@ -98,7 +98,7 @@ void example()
|
|||||||
// Customary Units (int)
|
// Customary Units (int)
|
||||||
{
|
{
|
||||||
using namespace units::physical::international::literals;
|
using namespace units::physical::international::literals;
|
||||||
constexpr Length AUTO distance = 140q_mi; // constructed from a UDL
|
constexpr Length auto distance = 140q_mi; // constructed from a UDL
|
||||||
constexpr si::time<si::hour, int> duration(2); // constructed from a value
|
constexpr si::time<si::hour, int> duration(2); // constructed from a value
|
||||||
|
|
||||||
std::cout << "\nUS Customary Units with 'int' as representation\n";
|
std::cout << "\nUS Customary Units with 'int' as representation\n";
|
||||||
@ -114,7 +114,7 @@ void example()
|
|||||||
// Customary Units (double)
|
// Customary Units (double)
|
||||||
{
|
{
|
||||||
using namespace units::physical::international::literals;
|
using namespace units::physical::international::literals;
|
||||||
constexpr Length AUTO distance = 140.q_mi; // constructed from a UDL
|
constexpr Length auto distance = 140.q_mi; // constructed from a UDL
|
||||||
constexpr si::time<si::hour> duration(2); // constructed from a value
|
constexpr si::time<si::hour> duration(2); // constructed from a value
|
||||||
|
|
||||||
std::cout << "\nUS Customary Units with 'double' as representation\n";
|
std::cout << "\nUS Customary Units with 'double' as representation\n";
|
||||||
@ -132,7 +132,7 @@ void example()
|
|||||||
// CGS (int)
|
// CGS (int)
|
||||||
{
|
{
|
||||||
using namespace units::physical::cgs::literals;
|
using namespace units::physical::cgs::literals;
|
||||||
constexpr Length AUTO distance = 22'000'000q_cm; // constructed from a UDL
|
constexpr Length auto distance = 22'000'000q_cm; // constructed from a UDL
|
||||||
constexpr cgs::time<si::hour, int> duration(2); // constructed from a value
|
constexpr cgs::time<si::hour, int> duration(2); // constructed from a value
|
||||||
|
|
||||||
std::cout << "\nCGS units with 'int' as representation\n";
|
std::cout << "\nCGS units with 'int' as representation\n";
|
||||||
@ -151,7 +151,7 @@ void example()
|
|||||||
// CGS (double)
|
// CGS (double)
|
||||||
{
|
{
|
||||||
using namespace units::physical::cgs::literals;
|
using namespace units::physical::cgs::literals;
|
||||||
constexpr Length AUTO distance = 22'000'000.q_cm; // constructed from a UDL
|
constexpr Length auto distance = 22'000'000.q_cm; // constructed from a UDL
|
||||||
constexpr cgs::time<si::hour> duration(2); // constructed from a value
|
constexpr cgs::time<si::hour> duration(2); // constructed from a value
|
||||||
|
|
||||||
std::cout << "\nCGS units with 'double' as representation\n";
|
std::cout << "\nCGS units with 'double' as representation\n";
|
||||||
|
@ -41,7 +41,7 @@ int main()
|
|||||||
constexpr auto R = 4.7q_kR;
|
constexpr auto R = 4.7q_kR;
|
||||||
|
|
||||||
for (auto t = 0q_ms; t <= 50q_ms; ++t) {
|
for (auto t = 0q_ms; t <= 50q_ms; ++t) {
|
||||||
const Voltage AUTO Vt = V0 * units::exp(-t / (R * C));
|
const Voltage auto Vt = V0 * units::exp(-t / (R * C));
|
||||||
|
|
||||||
std::cout << "at " << t << " voltage is ";
|
std::cout << "at " << t << " voltage is ";
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ int main()
|
|||||||
auto torque = 20.0q_Nm;
|
auto torque = 20.0q_Nm;
|
||||||
auto energy = 20.0q_J;
|
auto energy = 20.0q_J;
|
||||||
|
|
||||||
physical::Angle AUTO angle = torque / energy;
|
physical::Angle auto angle = torque / energy;
|
||||||
|
|
||||||
std::cout << angle << '\n';
|
std::cout << angle << '\n';
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,7 @@
|
|||||||
#include <units/quantity_point.h>
|
#include <units/quantity_point.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
#include <compare>
|
#include <compare>
|
||||||
#endif
|
|
||||||
|
|
||||||
// horizontal/vertical vector
|
// horizontal/vertical vector
|
||||||
namespace {
|
namespace {
|
||||||
@ -59,10 +56,8 @@ public:
|
|||||||
|
|
||||||
constexpr Q magnitude() const { return magnitude_; }
|
constexpr Q magnitude() const { return magnitude_; }
|
||||||
|
|
||||||
template<typename QQ = Q>
|
|
||||||
[[nodiscard]] constexpr vector operator-() const
|
[[nodiscard]] constexpr vector operator-() const
|
||||||
requires requires(QQ q) { -q; }
|
requires requires { -magnitude(); }
|
||||||
// requires requires { -magnitude(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
return vector(-magnitude());
|
return vector(-magnitude());
|
||||||
}
|
}
|
||||||
@ -92,15 +87,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
|
requires (Scalar<V> || Dimensionless<V>)
|
||||||
[[nodiscard]] friend constexpr auto operator*(const vector& lhs, const V& value)
|
[[nodiscard]] friend constexpr auto operator*(const vector& lhs, const V& value)
|
||||||
requires (Scalar<V> || Dimensionless<V>) && requires { lhs.magnitude() * value; }
|
requires requires { lhs.magnitude() * value; }
|
||||||
{
|
{
|
||||||
return vector<Q, D>(lhs.magnitude() * value);
|
return vector<Q, D>(lhs.magnitude() * value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
|
requires (Scalar<V> || Dimensionless<V>)
|
||||||
[[nodiscard]] friend constexpr auto operator*(const V& value, const vector& rhs)
|
[[nodiscard]] friend constexpr auto operator*(const V& value, const vector& rhs)
|
||||||
requires (Scalar<V> || Dimensionless<V>) && requires { value * rhs.magnitude(); }
|
requires requires { value * rhs.magnitude(); }
|
||||||
{
|
{
|
||||||
return vector<Q, D>(value * rhs.magnitude());
|
return vector<Q, D>(value * rhs.magnitude());
|
||||||
}
|
}
|
||||||
@ -112,8 +109,6 @@ public:
|
|||||||
return lhs.magnitude() / rhs.magnitude();
|
return lhs.magnitude() / rhs.magnitude();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
|
|
||||||
template<typename Q2>
|
template<typename Q2>
|
||||||
[[nodiscard]] friend constexpr auto operator<=>(const vector& lhs, const vector<Q2, D>& rhs)
|
[[nodiscard]] friend constexpr auto operator<=>(const vector& lhs, const vector<Q2, D>& rhs)
|
||||||
requires requires { lhs.magnitude() <=> rhs.magnitude(); }
|
requires requires { lhs.magnitude() <=> rhs.magnitude(); }
|
||||||
@ -128,56 +123,8 @@ public:
|
|||||||
return lhs.magnitude() == rhs.magnitude();
|
return lhs.magnitude() == rhs.magnitude();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
template<class CharT, class Traits>
|
||||||
|
requires Quantity<Q>
|
||||||
template<typename Q2>
|
|
||||||
[[nodiscard]] friend constexpr auto operator==(const vector& lhs, const vector<Q2, D>& rhs)
|
|
||||||
requires requires { lhs.magnitude() == rhs.magnitude(); }
|
|
||||||
{
|
|
||||||
return lhs.magnitude() == rhs.magnitude();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Q2>
|
|
||||||
[[nodiscard]] friend constexpr auto operator!=(const vector& lhs, const vector<Q2, D>& rhs)
|
|
||||||
requires requires { lhs.magnitude() != rhs.magnitude(); }
|
|
||||||
{
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Q2>
|
|
||||||
[[nodiscard]] friend constexpr auto operator<(const vector& lhs, const vector<Q2, D>& rhs)
|
|
||||||
requires requires { lhs.magnitude() < rhs.magnitude(); }
|
|
||||||
{
|
|
||||||
return lhs.magnitude() < rhs.magnitude();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Q2>
|
|
||||||
[[nodiscard]] friend constexpr auto operator>(const vector& lhs, const vector<Q2, D>& rhs)
|
|
||||||
requires requires { lhs.magnitude() > rhs.magnitude(); }
|
|
||||||
{
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Q2>
|
|
||||||
[[nodiscard]] friend constexpr auto operator<=(const vector& lhs, const vector<Q2, D>& rhs)
|
|
||||||
requires requires { lhs.magnitude() <= rhs.magnitude(); }
|
|
||||||
{
|
|
||||||
return !(rhs < lhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Q2>
|
|
||||||
[[nodiscard]] friend constexpr auto operator>=(const vector& lhs, const vector<Q2, D>& rhs)
|
|
||||||
requires requires { lhs.magnitude() >= rhs.magnitude(); }
|
|
||||||
{
|
|
||||||
return !(lhs < rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// template<class CharT, class Traits>
|
|
||||||
// requires Quantity<Q> // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
template<class CharT, class Traits, typename QQ = Q>
|
|
||||||
requires Quantity<QQ>
|
|
||||||
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const vector& v)
|
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const vector& v)
|
||||||
{
|
{
|
||||||
return os << v.magnitude();
|
return os << v.magnitude();
|
||||||
@ -278,7 +225,7 @@ auto get_gliders()
|
|||||||
return gliders;
|
return gliders;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Dimensionless AUTO glide_ratio(const glider::polar_point& polar)
|
constexpr Dimensionless auto glide_ratio(const glider::polar_point& polar)
|
||||||
{
|
{
|
||||||
return polar.v / -polar.climb;
|
return polar.v / -polar.climb;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
using namespace units::physical;
|
using namespace units::physical;
|
||||||
|
|
||||||
constexpr Speed AUTO avg_speed(Length AUTO d, Time AUTO t)
|
constexpr Speed auto avg_speed(Length auto d, Time auto t)
|
||||||
{
|
{
|
||||||
return d / t;
|
return d / t;
|
||||||
}
|
}
|
||||||
@ -35,10 +35,10 @@ constexpr Speed AUTO avg_speed(Length AUTO d, Time AUTO t)
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
using namespace units::physical::si::literals;
|
using namespace units::physical::si::literals;
|
||||||
Speed AUTO v1 = avg_speed(220q_km, 2q_h);
|
Speed auto v1 = avg_speed(220q_km, 2q_h);
|
||||||
Speed AUTO v2 = avg_speed(si::length<international::mile>(140), si::time<si::hour>(2));
|
Speed auto v2 = avg_speed(si::length<international::mile>(140), si::time<si::hour>(2));
|
||||||
Speed AUTO v3 = quantity_cast<si::metre_per_second>(v2);
|
Speed auto v3 = quantity_cast<si::metre_per_second>(v2);
|
||||||
Speed AUTO v4 = quantity_cast<int>(v3);
|
Speed auto v4 = quantity_cast<int>(v3);
|
||||||
|
|
||||||
std::cout << v1 << '\n'; // 110 km/h
|
std::cout << v1 << '\n'; // 110 km/h
|
||||||
std::cout << fmt::format("{}", v2) << '\n'; // 70 mi/h
|
std::cout << fmt::format("{}", v2) << '\n'; // 70 mi/h
|
||||||
|
@ -22,11 +22,8 @@
|
|||||||
|
|
||||||
#include <units/physical/si/acceleration.h>
|
#include <units/physical/si/acceleration.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
#include <compare>
|
#include <compare>
|
||||||
#endif
|
#include <iostream>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -105,41 +102,8 @@ public:
|
|||||||
return measurement(val, val * rhs.relative_uncertainty());
|
return measurement(val, val * rhs.relative_uncertainty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr auto operator<=>(const measurement&) const = default;
|
[[nodiscard]] constexpr auto operator<=>(const measurement&) const = default;
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator==(const measurement& lhs, const measurement& rhs)
|
|
||||||
{
|
|
||||||
return lhs.value() == rhs.value() && lhs.uncertainty() == rhs.uncertainty();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator!=(const measurement& lhs, const measurement& rhs)
|
|
||||||
{
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator<(const measurement& lhs, const measurement& rhs)
|
|
||||||
{
|
|
||||||
return lhs.value() == rhs.value() ? lhs.uncertainty() < rhs.uncertainty() : lhs.value() < rhs.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator>(const measurement& lhs, const measurement& rhs) { return rhs < lhs; }
|
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator<=(const measurement& lhs, const measurement& rhs)
|
|
||||||
{
|
|
||||||
return !(rhs < lhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator>=(const measurement& lhs, const measurement& rhs)
|
|
||||||
{
|
|
||||||
return !(lhs < rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& os, const measurement& v)
|
friend std::ostream& operator<<(std::ostream& os, const measurement& v)
|
||||||
{
|
{
|
||||||
return os << v.value() << " ± " << v.uncertainty();
|
return os << v.value() << " ± " << v.uncertainty();
|
||||||
@ -166,7 +130,7 @@ void example()
|
|||||||
const auto a = si::acceleration<si::metre_per_second_sq, measurement<double>>(measurement(9.8, 0.1));
|
const auto a = si::acceleration<si::metre_per_second_sq, measurement<double>>(measurement(9.8, 0.1));
|
||||||
const auto t = si::time<si::second, measurement<double>>(measurement(1.2, 0.1));
|
const auto t = si::time<si::second, measurement<double>>(measurement(1.2, 0.1));
|
||||||
|
|
||||||
const Speed AUTO v1 = a * t;
|
const Speed auto v1 = a * t;
|
||||||
std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::kilometre_per_hour>(v1) << '\n';
|
std::cout << a << " * " << t << " = " << v1 << " = " << quantity_cast<si::kilometre_per_hour>(v1) << '\n';
|
||||||
|
|
||||||
si::length<si::metre, measurement<double>> length(measurement(123., 1.));
|
si::length<si::metre, measurement<double>> length(measurement(123., 1.));
|
||||||
|
@ -32,7 +32,7 @@ namespace {
|
|||||||
|
|
||||||
using namespace units::physical;
|
using namespace units::physical;
|
||||||
|
|
||||||
Energy AUTO total_energy(Momentum AUTO p, Mass AUTO m, Speed AUTO c)
|
Energy auto total_energy(Momentum auto p, Mass auto m, Speed auto c)
|
||||||
{
|
{
|
||||||
return sqrt(pow<2>(p * c) + pow<2>(m * pow<2>(c)));
|
return sqrt(pow<2>(p * c) + pow<2>(m * pow<2>(c)));
|
||||||
}
|
}
|
||||||
@ -42,13 +42,13 @@ void si_example()
|
|||||||
using namespace units::physical::si;
|
using namespace units::physical::si;
|
||||||
using GeV = gigaelectronvolt;
|
using GeV = gigaelectronvolt;
|
||||||
|
|
||||||
constexpr Speed AUTO c = si2019::speed_of_light<>;
|
constexpr Speed auto c = si2019::speed_of_light<>;
|
||||||
|
|
||||||
std::cout << "\n*** SI units (c = " << c << ") ***\n";
|
std::cout << "\n*** SI units (c = " << c << ") ***\n";
|
||||||
|
|
||||||
const Momentum AUTO p = 4.q_GeV / c;
|
const Momentum auto p = 4.q_GeV / c;
|
||||||
const Mass AUTO m = 3.q_GeV / pow<2>(c);
|
const Mass auto m = 3.q_GeV / pow<2>(c);
|
||||||
const Energy AUTO E = total_energy(p, m, c);
|
const Energy auto E = total_energy(p, m, c);
|
||||||
|
|
||||||
std::cout << "[in GeV]\n"
|
std::cout << "[in GeV]\n"
|
||||||
<< "p = " << p << "\n"
|
<< "p = " << p << "\n"
|
||||||
@ -73,10 +73,10 @@ void natural_example()
|
|||||||
using namespace units::physical::natural;
|
using namespace units::physical::natural;
|
||||||
using GeV = gigaelectronvolt;
|
using GeV = gigaelectronvolt;
|
||||||
|
|
||||||
constexpr Speed AUTO c = speed_of_light<>;
|
constexpr Speed auto c = speed_of_light<>;
|
||||||
const momentum<GeV> p(4);
|
const momentum<GeV> p(4);
|
||||||
const mass<GeV> m(3);
|
const mass<GeV> m(3);
|
||||||
const Energy AUTO E = total_energy(p, m, c);
|
const Energy auto E = total_energy(p, m, c);
|
||||||
|
|
||||||
std::cout << "\n*** Natural units (c = " << c << ") ***\n"
|
std::cout << "\n*** Natural units (c = " << c << ") ***\n"
|
||||||
<< "p = " << p << "\n"
|
<< "p = " << p << "\n"
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template<units::physical::Length D, units::physical::Time T>
|
template<units::physical::Length D, units::physical::Time T>
|
||||||
constexpr units::physical::Speed AUTO avg_speed(D d, T t)
|
constexpr units::physical::Speed auto avg_speed(D d, T t)
|
||||||
{
|
{
|
||||||
return d / t;
|
return d / t;
|
||||||
}
|
}
|
||||||
@ -36,13 +36,13 @@ void example()
|
|||||||
using namespace units::physical;
|
using namespace units::physical;
|
||||||
using namespace units::physical::si::literals;
|
using namespace units::physical::si::literals;
|
||||||
|
|
||||||
Length AUTO d1 = 123q_m;
|
Length auto d1 = 123q_m;
|
||||||
Time AUTO t1 = 10q_s;
|
Time auto t1 = 10q_s;
|
||||||
Speed AUTO v1 = avg_speed(d1, t1);
|
Speed auto v1 = avg_speed(d1, t1);
|
||||||
|
|
||||||
auto temp1 = v1 * 50q_m; // produces intermediate unknown dimension with 'unknown_coherent_unit' as its 'coherent_unit'
|
auto temp1 = v1 * 50q_m; // produces intermediate unknown dimension with 'unknown_coherent_unit' as its 'coherent_unit'
|
||||||
Speed AUTO v2 = temp1 / 100q_m; // back to known dimensions again
|
Speed auto v2 = temp1 / 100q_m; // back to known dimensions again
|
||||||
Length AUTO d2 = v2 * 60q_s;
|
Length auto d2 = v2 * 60q_s;
|
||||||
|
|
||||||
std::cout << "d1 = " << d1 << '\n';
|
std::cout << "d1 = " << d1 << '\n';
|
||||||
std::cout << "t1 = " << t1 << '\n';
|
std::cout << "t1 = " << t1 << '\n';
|
||||||
|
@ -74,17 +74,6 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|||||||
-Wno-literal-suffix
|
-Wno-literal-suffix
|
||||||
-Wno-non-template-friend
|
-Wno-non-template-friend
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0)
|
|
||||||
target_compile_options(mp-units
|
|
||||||
INTERFACE
|
|
||||||
-fconcepts
|
|
||||||
)
|
|
||||||
target_link_libraries(mp-units
|
|
||||||
INTERFACE
|
|
||||||
$<IF:$<TARGET_EXISTS:CONAN_PKG::range-v3>,CONAN_PKG::range-v3,range-v3::range-v3>
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
target_compile_options(mp-units
|
target_compile_options(mp-units
|
||||||
INTERFACE
|
INTERFACE
|
||||||
|
@ -76,16 +76,8 @@ using common_quantity_point = decltype(
|
|||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
namespace concepts {
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<units::Quantity Q1, units::Quantity Q2>
|
template<units::Quantity Q1, units::Quantity Q2>
|
||||||
requires units::equivalent_dim<typename Q1::dimension, typename Q2::dimension>
|
requires units::equivalent_dim<typename Q1::dimension, typename Q2::dimension>
|
||||||
struct common_type<Q1, Q2> {
|
struct common_type<Q1, Q2> {
|
||||||
|
73
src/include/units/bits/external/fixed_string.h
vendored
73
src/include/units/bits/external/fixed_string.h
vendored
@ -26,10 +26,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
#include <compare>
|
#include <compare>
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
@ -76,8 +73,6 @@ struct basic_fixed_string {
|
|||||||
return basic_fixed_string<CharT, N + N2>(txt);
|
return basic_fixed_string<CharT, N + N2>(txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool operator==(const basic_fixed_string& other) const
|
[[nodiscard]] constexpr bool operator==(const basic_fixed_string& other) const
|
||||||
{
|
{
|
||||||
return std::ranges::equal(*this, other);
|
return std::ranges::equal(*this, other);
|
||||||
@ -92,74 +87,6 @@ struct basic_fixed_string {
|
|||||||
return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
return std::lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(const basic_fixed_string& lhs, const basic_fixed_string& rhs) noexcept
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i != lhs.size(); ++i)
|
|
||||||
if (lhs.data_[i] != rhs.data_[i]) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator!=(const basic_fixed_string& lhs, const basic_fixed_string& rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(const basic_fixed_string&,
|
|
||||||
const basic_fixed_string<CharT2, N2>&) noexcept
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator!=(const basic_fixed_string&,
|
|
||||||
const basic_fixed_string<CharT2, N2>&) noexcept
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator<(const basic_fixed_string& lhs,
|
|
||||||
const basic_fixed_string<CharT2, N2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
using std::begin, std::end;
|
|
||||||
auto first1 = begin(lhs.data_);
|
|
||||||
auto first2 = begin(rhs.data_);
|
|
||||||
const auto last1 = std::prev(end(lhs.data_)); // do not waste time for '\0'
|
|
||||||
const auto last2 = std::prev(end(rhs.data_));
|
|
||||||
|
|
||||||
for (; (first1 != last1) && (first2 != last2); ++first1, (void)++first2) {
|
|
||||||
if (*first1 < *first2) return true;
|
|
||||||
if (*first2 < *first1) return false;
|
|
||||||
}
|
|
||||||
return first1 == last1 && first2 != last2;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator>(const basic_fixed_string& lhs,
|
|
||||||
const basic_fixed_string<CharT2, N2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator<=(const basic_fixed_string& lhs,
|
|
||||||
const basic_fixed_string<CharT2, N2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(rhs < lhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator>=(const basic_fixed_string& lhs,
|
|
||||||
const basic_fixed_string<CharT2, N2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(lhs < rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<class Traits>
|
template<class Traits>
|
||||||
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
|
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
|
||||||
const basic_fixed_string& txt)
|
const basic_fixed_string& txt)
|
||||||
|
77
src/include/units/bits/external/hacks.h
vendored
77
src/include/units/bits/external/hacks.h
vendored
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <concepts>
|
||||||
|
|
||||||
#if __clang__
|
#if __clang__
|
||||||
#define COMP_CLANG __clang_major__
|
#define COMP_CLANG __clang_major__
|
||||||
@ -33,29 +33,6 @@
|
|||||||
#define COMP_MSVC _MSC_VER
|
#define COMP_MSVC _MSC_VER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
|
|
||||||
#include <concepts>
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <concepts/concepts.hpp>
|
|
||||||
#include <range/v3/range.hpp>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10 || COMP_CLANG >= 11
|
|
||||||
|
|
||||||
#define AUTO auto
|
|
||||||
#define SAME_AS(T) std::same_as<T>
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define AUTO
|
|
||||||
#define SAME_AS(T) T
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if COMP_MSVC
|
#if COMP_MSVC
|
||||||
|
|
||||||
#define TYPENAME typename
|
#define TYPENAME typename
|
||||||
@ -66,53 +43,13 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if COMP_GCC
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
#if COMP_GCC
|
template<class T>
|
||||||
#if COMP_GCC >= 10
|
concept default_constructible = constructible_from<T>;
|
||||||
|
|
||||||
template<class T>
|
|
||||||
concept default_constructible = constructible_from<T>;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// concepts
|
|
||||||
using concepts::common_reference_with;
|
|
||||||
using concepts::common_with;
|
|
||||||
using concepts::constructible_from;
|
|
||||||
using concepts::convertible_to;
|
|
||||||
using concepts::default_constructible;
|
|
||||||
using concepts::derived_from;
|
|
||||||
using concepts::equality_comparable;
|
|
||||||
using concepts::equality_comparable_with;
|
|
||||||
// using concepts::floating_point;
|
|
||||||
using concepts::integral;
|
|
||||||
using concepts::regular;
|
|
||||||
using concepts::same_as;
|
|
||||||
using concepts::totally_ordered;
|
|
||||||
using concepts::totally_ordered_with;
|
|
||||||
|
|
||||||
namespace ranges {
|
|
||||||
|
|
||||||
using ::ranges::forward_range;
|
|
||||||
using ::ranges::range_value_t;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// missing in Range-v3
|
|
||||||
template<class T>
|
|
||||||
concept floating_point = std::is_floating_point_v<T>;
|
|
||||||
|
|
||||||
template<class F, class... Args>
|
|
||||||
concept invocable =
|
|
||||||
requires(F&& f, Args&&... args) {
|
|
||||||
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class F, class... Args>
|
|
||||||
concept regular_invocable = invocable<F, Args...>;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <units/bits/external/hacks.h>
|
#include <units/bits/external/hacks.h>
|
||||||
#include <units/ratio.h>
|
#include <units/ratio.h>
|
||||||
#include <units/bits/external/type_traits.h>
|
#include <units/bits/external/type_traits.h>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace units {
|
|||||||
*/
|
*/
|
||||||
template<std::intmax_t N, Quantity Q>
|
template<std::intmax_t N, Quantity Q>
|
||||||
requires(N != 0)
|
requires(N != 0)
|
||||||
inline Quantity AUTO pow(const Q& q) noexcept
|
inline Quantity auto pow(const Q& q) noexcept
|
||||||
requires requires { std::pow(q.count(), N); }
|
requires requires { std::pow(q.count(), N); }
|
||||||
{
|
{
|
||||||
using dim = dimension_pow<typename Q::dimension, N>;
|
using dim = dimension_pow<typename Q::dimension, N>;
|
||||||
@ -70,7 +70,7 @@ inline TYPENAME Q::rep pow(const Q&) noexcept
|
|||||||
* @return Quantity The result of computation
|
* @return Quantity The result of computation
|
||||||
*/
|
*/
|
||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
inline Quantity AUTO sqrt(const Q& q) noexcept
|
inline Quantity auto sqrt(const Q& q) noexcept
|
||||||
requires requires { std::sqrt(q.count()); }
|
requires requires { std::sqrt(q.count()); }
|
||||||
{
|
{
|
||||||
using dim = dimension_sqrt<typename Q::dimension>;
|
using dim = dimension_sqrt<typename Q::dimension>;
|
||||||
@ -99,7 +99,7 @@ inline quantity<D, U, Rep> exp(const quantity<D, U, Rep>& q)
|
|||||||
* @return Quantity The absolute value of a provided quantity
|
* @return Quantity The absolute value of a provided quantity
|
||||||
*/
|
*/
|
||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
inline Quantity AUTO abs(const Q& q) noexcept
|
inline Quantity auto abs(const Q& q) noexcept
|
||||||
requires requires { std::abs(q.count()); }
|
requires requires { std::abs(q.count()); }
|
||||||
{
|
{
|
||||||
return Q(std::abs(q.count()));
|
return Q(std::abs(q.count()));
|
||||||
@ -115,7 +115,7 @@ inline Quantity AUTO abs(const Q& q) noexcept
|
|||||||
*/
|
*/
|
||||||
template<Quantity Q>
|
template<Quantity Q>
|
||||||
requires requires { std::numeric_limits<typename Q::rep>::epsilon(); }
|
requires requires { std::numeric_limits<typename Q::rep>::epsilon(); }
|
||||||
constexpr Quantity AUTO epsilon() noexcept
|
constexpr Quantity auto epsilon() noexcept
|
||||||
{
|
{
|
||||||
return Q(std::numeric_limits<typename Q::rep>::epsilon());
|
return Q(std::numeric_limits<typename Q::rep>::epsilon());
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,7 @@
|
|||||||
#include <units/bits/to_string.h>
|
#include <units/bits/to_string.h>
|
||||||
#include <units/dimensionless.h>
|
#include <units/dimensionless.h>
|
||||||
#include <units/quantity_cast.h>
|
#include <units/quantity_cast.h>
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
#include <compare>
|
#include <compare>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
@ -90,78 +86,60 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] constexpr rep count() const noexcept { return value_; }
|
[[nodiscard]] constexpr rep count() const noexcept { return value_; }
|
||||||
|
|
||||||
template<typename T = Rep>
|
|
||||||
[[nodiscard]] static constexpr quantity zero() noexcept
|
[[nodiscard]] static constexpr quantity zero() noexcept
|
||||||
requires requires { quantity_values<T>::zero(); }
|
requires requires { quantity_values<Rep>::zero(); }
|
||||||
// requires requires { quantity_values<Rep>::zero(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
return quantity(quantity_values<Rep>::zero());
|
return quantity(quantity_values<Rep>::zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = Rep>
|
|
||||||
[[nodiscard]] static constexpr quantity one() noexcept
|
[[nodiscard]] static constexpr quantity one() noexcept
|
||||||
requires requires { quantity_values<T>::one(); }
|
requires requires { quantity_values<Rep>::one(); }
|
||||||
// requires requires { quantity_values<Rep>::one(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
return quantity(quantity_values<Rep>::one());
|
return quantity(quantity_values<Rep>::one());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = Rep>
|
|
||||||
[[nodiscard]] static constexpr quantity min() noexcept
|
[[nodiscard]] static constexpr quantity min() noexcept
|
||||||
requires requires { quantity_values<T>::min(); }
|
requires requires { quantity_values<Rep>::min(); }
|
||||||
// requires requires { quantity_values<Rep>::min(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
return quantity(quantity_values<Rep>::min());
|
return quantity(quantity_values<Rep>::min());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = Rep>
|
|
||||||
[[nodiscard]] static constexpr quantity max() noexcept
|
[[nodiscard]] static constexpr quantity max() noexcept
|
||||||
requires requires { quantity_values<T>::max(); }
|
requires requires { quantity_values<Rep>::max(); }
|
||||||
// requires requires { quantity_values<Rep>::max(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
return quantity(quantity_values<Rep>::max());
|
return quantity(quantity_values<Rep>::max());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr quantity operator+() const { return *this; }
|
[[nodiscard]] constexpr quantity operator+() const { return *this; }
|
||||||
|
|
||||||
template<typename T = Rep>
|
|
||||||
[[nodiscard]] constexpr quantity operator-() const
|
[[nodiscard]] constexpr quantity operator-() const
|
||||||
requires std::regular_invocable<std::negate<>, T>
|
requires std::regular_invocable<std::negate<>, rep>
|
||||||
// requires std::regular_invocable<std::negate<>, rep> // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
return quantity(-count());
|
return quantity(-count());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = Rep>
|
|
||||||
constexpr quantity& operator++()
|
constexpr quantity& operator++()
|
||||||
requires requires(T v) { { ++v } -> SAME_AS(T&); }
|
requires requires(rep v) { { ++v } -> std::same_as<rep&>; }
|
||||||
// requires requires(rep v) { { ++v } -> std::same_as<rep&>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
++value_;
|
++value_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = Rep>
|
|
||||||
[[nodiscard]] constexpr quantity operator++(int)
|
[[nodiscard]] constexpr quantity operator++(int)
|
||||||
requires requires(T v) { { v++ } -> SAME_AS(T); }
|
requires requires(rep v) { { v++ } -> std::same_as<rep>; }
|
||||||
// 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>
|
|
||||||
constexpr quantity& operator--()
|
constexpr quantity& operator--()
|
||||||
requires requires(T v) { { --v } -> SAME_AS(T&); }
|
requires requires(rep v) { { --v } -> std::same_as<rep&>; }
|
||||||
// requires requires(rep v) { { --v } -> std::same_as<rep&>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
--value_;
|
--value_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = Rep>
|
|
||||||
[[nodiscard]] constexpr quantity operator--(int)
|
[[nodiscard]] constexpr quantity operator--(int)
|
||||||
requires requires(T v) { { v-- } -> SAME_AS(T); }
|
requires requires(rep v) { { v-- } -> std::same_as<rep>; }
|
||||||
// requires requires(rep v) { { v-- } -> std::same_as<rep>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
return quantity(value_--);
|
return quantity(value_--);
|
||||||
}
|
}
|
||||||
@ -198,22 +176,19 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Scalar Value, typename T = Rep>
|
template<Scalar Value>
|
||||||
constexpr quantity& operator%=(const Value& rhs)
|
|
||||||
requires (!treat_as_floating_point<rep>) &&
|
requires (!treat_as_floating_point<rep>) &&
|
||||||
(!treat_as_floating_point<Value>) &&
|
(!treat_as_floating_point<Value>)
|
||||||
requires(T v1, Value v2) { { v1 %= v2 } -> SAME_AS(T&); }
|
constexpr quantity& operator%=(const Value& rhs)
|
||||||
// requires(rep v1, Value v2) { { v1 %= v2 } -> SAME_AS(rep&); } // TODO gated by gcc-9 (fixed in gcc-10)
|
requires requires(rep v1, Value v2) { { v1 %= v2 } -> std::same_as<rep&>; }
|
||||||
{
|
{
|
||||||
value_ %= rhs;
|
value_ %= rhs;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T = Rep>
|
|
||||||
constexpr quantity& operator%=(const quantity& q)
|
constexpr quantity& operator%=(const quantity& q)
|
||||||
requires (!treat_as_floating_point<rep>) &&
|
requires (!treat_as_floating_point<rep>) &&
|
||||||
requires(T v1, T v2) { { v1 %= v2 } -> SAME_AS(T&); }
|
requires(rep v1, rep v2) { { v1 %= v2 } -> std::same_as<rep&>; }
|
||||||
// requires(rep v1, rep v2) { { v1 %= v2 } -> std::same_as<rep&>; } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
value_ %= q.count();
|
value_ %= q.count();
|
||||||
return *this;
|
return *this;
|
||||||
@ -229,8 +204,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename U2, typename Rep2>
|
template<typename U2, typename Rep2>
|
||||||
[[nodiscard]] friend constexpr Quantity AUTO operator+(const quantity& lhs, const quantity<D, U2, Rep2>& rhs)
|
|
||||||
requires std::regular_invocable<std::plus<>, Rep, Rep2>
|
requires std::regular_invocable<std::plus<>, Rep, Rep2>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator+(const quantity& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
using common_rep = decltype(lhs.count() + rhs.count());
|
using common_rep = decltype(lhs.count() + rhs.count());
|
||||||
using ret = common_quantity<quantity, quantity<D, U2, Rep2>, common_rep>;
|
using ret = common_quantity<quantity, quantity<D, U2, Rep2>, common_rep>;
|
||||||
@ -244,8 +219,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename U2, typename Rep2>
|
template<typename U2, typename Rep2>
|
||||||
[[nodiscard]] friend constexpr Quantity AUTO operator-(const quantity& lhs, const quantity<D, U2, Rep2>& rhs)
|
|
||||||
requires std::regular_invocable<std::minus<>, Rep, Rep2>
|
requires std::regular_invocable<std::minus<>, Rep, Rep2>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
using common_rep = decltype(lhs.count() - rhs.count());
|
using common_rep = decltype(lhs.count() - rhs.count());
|
||||||
using ret = common_quantity<quantity, quantity<D, U2, Rep2>, common_rep>;
|
using ret = common_quantity<quantity, quantity<D, U2, Rep2>, common_rep>;
|
||||||
@ -253,8 +228,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<Scalar Value>
|
template<Scalar Value>
|
||||||
[[nodiscard]] friend constexpr Quantity AUTO operator*(const quantity& q, const Value& v)
|
|
||||||
requires std::regular_invocable<std::multiplies<>, Rep, Value>
|
requires std::regular_invocable<std::multiplies<>, Rep, Value>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator*(const quantity& q, const Value& v)
|
||||||
{
|
{
|
||||||
using common_rep = decltype(q.count() * v);
|
using common_rep = decltype(q.count() * v);
|
||||||
using ret = quantity<D, U, common_rep>;
|
using ret = quantity<D, U, common_rep>;
|
||||||
@ -262,15 +237,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<Scalar Value>
|
template<Scalar Value>
|
||||||
[[nodiscard]] friend constexpr Quantity AUTO operator*(const Value& v, const quantity& q)
|
|
||||||
requires std::regular_invocable<std::multiplies<>, Value, Rep>
|
requires std::regular_invocable<std::multiplies<>, Value, Rep>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator*(const Value& v, const quantity& q)
|
||||||
{
|
{
|
||||||
return q * v;
|
return q * v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename D2, typename U2, typename Rep2>
|
template<typename D2, typename U2, typename Rep2>
|
||||||
[[nodiscard]] friend constexpr Quantity AUTO operator*(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
|
||||||
requires std::regular_invocable<std::multiplies<>, Rep, Rep2>
|
requires std::regular_invocable<std::multiplies<>, Rep, Rep2>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator*(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
using dim = dimension_multiply<D, D2>;
|
using dim = dimension_multiply<D, D2>;
|
||||||
using ret_unit = downcast_unit<dim, (U::ratio / dimension_unit<D>::ratio) * (U2::ratio / dimension_unit<D2>::ratio) * dimension_unit<dim>::ratio>;
|
using ret_unit = downcast_unit<dim, (U::ratio / dimension_unit<D>::ratio) * (U2::ratio / dimension_unit<D2>::ratio) * dimension_unit<dim>::ratio>;
|
||||||
@ -280,8 +255,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<Scalar Value>
|
template<Scalar Value>
|
||||||
[[nodiscard]] friend constexpr Quantity AUTO operator/(const Value& v, const quantity& q)
|
|
||||||
requires std::regular_invocable<std::divides<>, Value, Rep>
|
requires std::regular_invocable<std::divides<>, Value, Rep>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator/(const Value& v, const quantity& q)
|
||||||
{
|
{
|
||||||
Expects(q.count() != 0);
|
Expects(q.count() != 0);
|
||||||
|
|
||||||
@ -293,8 +268,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<Scalar Value>
|
template<Scalar Value>
|
||||||
[[nodiscard]] friend constexpr Quantity AUTO operator/(const quantity& q, const Value& v)
|
|
||||||
requires std::regular_invocable<std::divides<>, Rep, Value>
|
requires std::regular_invocable<std::divides<>, Rep, Value>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator/(const quantity& q, const Value& v)
|
||||||
{
|
{
|
||||||
Expects(v != Value{0});
|
Expects(v != Value{0});
|
||||||
|
|
||||||
@ -304,8 +279,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename D2, typename U2, typename Rep2>
|
template<typename D2, typename U2, typename Rep2>
|
||||||
[[nodiscard]] friend constexpr Quantity AUTO operator/(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
|
||||||
requires std::regular_invocable<std::divides<>, Rep, Rep2>
|
requires std::regular_invocable<std::divides<>, Rep, Rep2>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator/(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
Expects(rhs.count() != 0);
|
Expects(rhs.count() != 0);
|
||||||
|
|
||||||
@ -317,10 +292,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<Scalar Value>
|
template<Scalar Value>
|
||||||
[[nodiscard]] friend constexpr Quantity AUTO operator%(const quantity& q, const Value& v)
|
|
||||||
requires (!treat_as_floating_point<Rep>) &&
|
requires (!treat_as_floating_point<Rep>) &&
|
||||||
(!treat_as_floating_point<Value>) &&
|
(!treat_as_floating_point<Value>) &&
|
||||||
std::regular_invocable<std::modulus<>, Rep, Value>
|
std::regular_invocable<std::modulus<>, Rep, Value>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& q, const Value& v)
|
||||||
{
|
{
|
||||||
using common_rep = decltype(q.count() % v);
|
using common_rep = decltype(q.count() % v);
|
||||||
using ret = quantity<D, U, common_rep>;
|
using ret = quantity<D, U, common_rep>;
|
||||||
@ -328,90 +303,34 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename U2, typename Rep2>
|
template<typename U2, typename Rep2>
|
||||||
[[nodiscard]] friend constexpr Quantity AUTO operator%(const quantity& lhs, const quantity<D, U2, Rep2>& rhs)
|
|
||||||
requires (!treat_as_floating_point<Rep>) &&
|
requires (!treat_as_floating_point<Rep>) &&
|
||||||
(!treat_as_floating_point<Rep2>) &&
|
(!treat_as_floating_point<Rep2>) &&
|
||||||
std::regular_invocable<std::modulus<>, Rep, Rep2>
|
std::regular_invocable<std::modulus<>, Rep, Rep2>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator%(const quantity& lhs, const quantity<D, U2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
using common_rep = decltype(lhs.count() % rhs.count());
|
using common_rep = decltype(lhs.count() % rhs.count());
|
||||||
using ret = common_quantity<quantity, quantity<D, U2, Rep2>, common_rep>;
|
using ret = common_quantity<quantity, quantity<D, U2, Rep2>, common_rep>;
|
||||||
return ret(ret(lhs).count() % ret(rhs).count());
|
return ret(ret(lhs).count() % ret(rhs).count());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
|
|
||||||
template<typename D2, typename U2, typename Rep2>
|
template<typename D2, typename U2, typename Rep2>
|
||||||
[[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
|
||||||
requires equivalent_dim<D, D2> &&
|
requires equivalent_dim<D, D2> &&
|
||||||
std::three_way_comparable_with<Rep, Rep2>
|
std::three_way_comparable_with<Rep, Rep2>
|
||||||
|
[[nodiscard]] friend constexpr auto operator<=>(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
||||||
return cq(lhs).count() <=> cq(rhs).count();
|
return cq(lhs).count() <=> cq(rhs).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename D2, typename U2, typename Rep2>
|
template<typename D2, typename U2, typename Rep2>
|
||||||
[[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
|
||||||
requires equivalent_dim<D, D2> &&
|
requires equivalent_dim<D, D2> &&
|
||||||
std::equality_comparable_with<Rep, Rep2>
|
std::equality_comparable_with<Rep, Rep2>
|
||||||
|
[[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
||||||
{
|
{
|
||||||
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
||||||
return cq(lhs).count() == cq(rhs).count();
|
return cq(lhs).count() == cq(rhs).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
template<typename D2, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
|
||||||
requires equivalent_dim<D, D2> &&
|
|
||||||
std::equality_comparable_with<Rep, Rep2>
|
|
||||||
{
|
|
||||||
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
|
||||||
return cq(lhs).count() == cq(rhs).count();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename D2, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] friend constexpr bool operator!=(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
|
||||||
requires equivalent_dim<D, D2> &&
|
|
||||||
std::equality_comparable_with<Rep, Rep2>
|
|
||||||
{
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename D2, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] friend constexpr bool operator<(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
|
||||||
requires equivalent_dim<D, D2> &&
|
|
||||||
std::totally_ordered_with<Rep, Rep2>
|
|
||||||
{
|
|
||||||
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
|
|
||||||
return cq(lhs).count() < cq(rhs).count();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename D2, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] friend constexpr bool operator<=(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
|
||||||
requires equivalent_dim<D, D2> &&
|
|
||||||
std::totally_ordered_with<Rep, Rep2>
|
|
||||||
{
|
|
||||||
return !(rhs < lhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename D2, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] friend constexpr bool operator>(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
|
||||||
requires equivalent_dim<D, D2> &&
|
|
||||||
std::totally_ordered_with<Rep, Rep2>
|
|
||||||
{
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename D2, typename U2, typename Rep2>
|
|
||||||
[[nodiscard]] friend constexpr bool operator>=(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
|
|
||||||
requires equivalent_dim<D, D2> &&
|
|
||||||
std::totally_ordered_with<Rep, Rep2>
|
|
||||||
{
|
|
||||||
return !(lhs < rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<class CharT, class Traits>
|
template<class CharT, class Traits>
|
||||||
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const quantity& q)
|
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const quantity& q)
|
||||||
{
|
{
|
||||||
|
@ -313,8 +313,8 @@ constexpr ratio cast_ratio(const Q1& from, const Q2& to)
|
|||||||
* @tparam To a target quantity type to cast to
|
* @tparam To a target quantity type to cast to
|
||||||
*/
|
*/
|
||||||
template<Quantity To, typename D, typename U, typename Rep>
|
template<Quantity To, typename D, typename U, typename Rep>
|
||||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
|
||||||
requires QuantityOf<To, D>
|
requires QuantityOf<To, D>
|
||||||
|
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||||
{
|
{
|
||||||
using c_ratio = std::integral_constant<ratio, detail::cast_ratio(quantity<D, U, Rep>(), To())>;
|
using c_ratio = std::integral_constant<ratio, detail::cast_ratio(quantity<D, U, Rep>(), To())>;
|
||||||
using c_rep = std::common_type_t<typename To::rep, Rep>;
|
using c_rep = std::common_type_t<typename To::rep, Rep>;
|
||||||
@ -337,8 +337,8 @@ template<Quantity To, typename D, typename U, typename Rep>
|
|||||||
* @tparam ToD a dimension type to use for a target quantity
|
* @tparam ToD a dimension type to use for a target quantity
|
||||||
*/
|
*/
|
||||||
template<Dimension ToD, typename D, typename U, typename Rep>
|
template<Dimension ToD, typename D, typename U, typename Rep>
|
||||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
|
||||||
requires equivalent_dim<ToD, D>
|
requires equivalent_dim<ToD, D>
|
||||||
|
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||||
{
|
{
|
||||||
return quantity_cast<quantity<ToD, dimension_unit<ToD>, Rep>>(q);
|
return quantity_cast<quantity<ToD, dimension_unit<ToD>, Rep>>(q);
|
||||||
}
|
}
|
||||||
@ -356,8 +356,8 @@ template<Dimension ToD, typename D, typename U, typename Rep>
|
|||||||
* @tparam ToU a unit type to use for a target quantity
|
* @tparam ToU a unit type to use for a target quantity
|
||||||
*/
|
*/
|
||||||
template<Unit ToU, typename D, typename U, typename Rep>
|
template<Unit ToU, typename D, typename U, typename Rep>
|
||||||
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
|
||||||
requires UnitOf<ToU, D>
|
requires UnitOf<ToU, D>
|
||||||
|
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
|
||||||
{
|
{
|
||||||
return quantity_cast<quantity<D, ToU, Rep>>(q);
|
return quantity_cast<quantity<D, ToU, Rep>>(q);
|
||||||
}
|
}
|
||||||
@ -397,9 +397,9 @@ template<Scalar ToRep, typename D, typename U, typename Rep>
|
|||||||
* @tparam CastSpec a target quantity point type to cast to or anything that works for quantity_cast
|
* @tparam CastSpec a target quantity point type to cast to or anything that works for quantity_cast
|
||||||
*/
|
*/
|
||||||
template<typename CastSpec, typename D, typename U, typename Rep>
|
template<typename CastSpec, typename D, typename U, typename Rep>
|
||||||
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<D, U, Rep>& qp)
|
|
||||||
requires is_specialization_of<CastSpec, quantity_point> ||
|
requires is_specialization_of<CastSpec, quantity_point> ||
|
||||||
requires(quantity<D, U, Rep> q) { quantity_cast<CastSpec>(q); }
|
requires(quantity<D, U, Rep> q) { quantity_cast<CastSpec>(q); }
|
||||||
|
[[nodiscard]] constexpr auto quantity_point_cast(const quantity_point<D, U, Rep>& qp)
|
||||||
{
|
{
|
||||||
if constexpr (is_specialization_of<CastSpec, quantity_point>)
|
if constexpr (is_specialization_of<CastSpec, quantity_point>)
|
||||||
return quantity_point(quantity_cast<typename CastSpec::quantity_type>(qp.relative()));
|
return quantity_point(quantity_cast<typename CastSpec::quantity_type>(qp.relative()));
|
||||||
|
@ -24,10 +24,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
#include <compare>
|
#include <compare>
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
@ -69,69 +66,53 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] constexpr quantity_type relative() const noexcept { return q_; }
|
[[nodiscard]] constexpr quantity_type relative() const noexcept { return q_; }
|
||||||
|
|
||||||
template<typename Q = quantity_type>
|
|
||||||
[[nodiscard]] static constexpr quantity_point min() noexcept
|
[[nodiscard]] static constexpr quantity_point min() noexcept
|
||||||
requires requires { Q::min(); }
|
requires requires { quantity_type::min(); }
|
||||||
// requires requires { quantity_type::min(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
return quantity_point(quantity_type::min());
|
return quantity_point(quantity_type::min());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Q = quantity_type>
|
|
||||||
[[nodiscard]] static constexpr quantity_point max() noexcept
|
[[nodiscard]] static constexpr quantity_point max() noexcept
|
||||||
requires requires { Q::max(); }
|
requires requires { quantity_type::max(); }
|
||||||
// requires requires { quantity_type::max(); } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
return quantity_point(quantity_type::max());
|
return quantity_point(quantity_type::max());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Q = quantity_type>
|
|
||||||
requires requires(Q q) { ++q; }
|
|
||||||
constexpr quantity_point& operator++()
|
constexpr quantity_point& operator++()
|
||||||
// requires requires(quantity_type q) { ++q; } // TODO gated by gcc-9 (fixed in gcc-10)
|
requires requires(quantity_type q) { ++q; }
|
||||||
{
|
{
|
||||||
++q_;
|
++q_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Q = quantity_type>
|
|
||||||
[[nodiscard]] constexpr quantity_point operator++(int)
|
[[nodiscard]] constexpr quantity_point operator++(int)
|
||||||
requires requires(Q q) { q++; }
|
requires requires(quantity_type q) { q++; }
|
||||||
// requires requires(quantity_type q) { q++; } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
return quantity_point(q_++);
|
return quantity_point(q_++);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Q = quantity_type>
|
|
||||||
requires requires(Q q) { --q; }
|
|
||||||
constexpr quantity_point& operator--()
|
constexpr quantity_point& operator--()
|
||||||
// requires requires(quantity_type q) { --q; } // TODO gated by gcc-9 (fixed in gcc-10)
|
requires requires(quantity_type q) { --q; }
|
||||||
{
|
{
|
||||||
--q_;
|
--q_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Q = quantity_type>
|
|
||||||
[[nodiscard]] constexpr quantity_point operator--(int)
|
[[nodiscard]] constexpr quantity_point operator--(int)
|
||||||
requires requires(Q q) { q--; }
|
requires requires(quantity_type q) { q--; }
|
||||||
// requires requires(quantity_type q) { q--; } // TODO gated by gcc-9 (fixed in gcc-10)
|
|
||||||
{
|
{
|
||||||
return quantity_point(q_--);
|
return quantity_point(q_--);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Q = quantity_type>
|
|
||||||
requires requires(Q q1, Q q2) { q1 += q2; }
|
|
||||||
constexpr quantity_point& operator+=(const quantity_type& q)
|
constexpr quantity_point& operator+=(const quantity_type& q)
|
||||||
// requires requires(quantity_type q) { q += q; } // TODO gated by gcc-9 (fixed in gcc-10)
|
requires requires(quantity_type q) { q += q; }
|
||||||
{
|
{
|
||||||
q_ += q;
|
q_ += q;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Q = quantity_type>
|
|
||||||
requires requires(Q q1, Q q2) { q1 -= q2; }
|
|
||||||
constexpr quantity_point& operator-=(const quantity_type& q)
|
constexpr quantity_point& operator-=(const quantity_type& q)
|
||||||
// requires requires(quantity_type q) { q1 -= q2; } // TODO gated by gcc-9 (fixed in gcc-10)
|
requires requires(quantity_type q1, quantity_type q2) { q1 -= q2; }
|
||||||
{
|
{
|
||||||
q_ -= q;
|
q_ -= q;
|
||||||
return *this;
|
return *this;
|
||||||
@ -139,100 +120,58 @@ public:
|
|||||||
|
|
||||||
// Hidden Friends
|
// Hidden Friends
|
||||||
// Below friend functions are to be found via argument-dependent lookup only
|
// Below friend functions are to be found via argument-dependent lookup only
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
|
template<Quantity Q>
|
||||||
|
[[nodiscard]] friend constexpr QuantityPoint auto operator+(const quantity_point& lhs, const Q& rhs)
|
||||||
|
requires requires { lhs.relative() + rhs; }
|
||||||
|
{
|
||||||
|
const auto q = lhs.relative() + rhs;
|
||||||
|
using q_type = decltype(q);
|
||||||
|
return quantity_point<typename q_type::dimension, typename q_type::unit, typename q_type::rep>(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Quantity Q>
|
||||||
|
[[nodiscard]] friend constexpr QuantityPoint auto operator+(const Q& lhs, const quantity_point& rhs)
|
||||||
|
requires requires { rhs + lhs; }
|
||||||
|
{
|
||||||
|
return rhs + lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Quantity Q>
|
||||||
|
[[nodiscard]] friend constexpr QuantityPoint auto operator-(const quantity_point& lhs, const Q& rhs)
|
||||||
|
requires requires { lhs.relative() - rhs; }
|
||||||
|
{
|
||||||
|
const auto q = lhs.relative() - rhs;
|
||||||
|
using q_type = decltype(q);
|
||||||
|
return quantity_point<typename q_type::dimension, typename q_type::unit, typename q_type::rep>(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<QuantityPoint QP>
|
||||||
|
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity_point& lhs, const QP& rhs)
|
||||||
|
requires requires { lhs.relative() - rhs.relative(); }
|
||||||
|
{
|
||||||
|
return lhs.relative() - rhs.relative();
|
||||||
|
}
|
||||||
|
|
||||||
template<QuantityPoint QP>
|
template<QuantityPoint QP>
|
||||||
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP& rhs)
|
|
||||||
requires std::three_way_comparable_with<quantity_type, typename QP::quantity_type>
|
requires std::three_way_comparable_with<quantity_type, typename QP::quantity_type>
|
||||||
|
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP& rhs)
|
||||||
{
|
{
|
||||||
return lhs.relative() <=> rhs.relative();
|
return lhs.relative() <=> rhs.relative();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<QuantityPoint QP>
|
template<QuantityPoint QP>
|
||||||
[[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP& rhs)
|
|
||||||
requires std::equality_comparable_with<quantity_type, typename QP::quantity_type>
|
requires std::equality_comparable_with<quantity_type, typename QP::quantity_type>
|
||||||
|
[[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP& rhs)
|
||||||
{
|
{
|
||||||
return lhs.relative() == rhs.relative();
|
return lhs.relative() == rhs.relative();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
template<QuantityPoint QP>
|
|
||||||
[[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP& rhs)
|
|
||||||
requires std::equality_comparable_with<quantity_type, typename QP::quantity_type>
|
|
||||||
{
|
|
||||||
return lhs.relative() == rhs.relative();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<QuantityPoint QP>
|
|
||||||
[[nodiscard]] friend constexpr bool operator!=(const quantity_point& lhs, const QP& rhs)
|
|
||||||
requires std::equality_comparable_with<quantity_type, typename QP::quantity_type>
|
|
||||||
{
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<QuantityPoint QP>
|
|
||||||
[[nodiscard]] friend constexpr bool operator<(const quantity_point& lhs, const QP& rhs)
|
|
||||||
requires std::totally_ordered_with<quantity_type, typename QP::quantity_type>
|
|
||||||
{
|
|
||||||
return lhs.relative() < rhs.relative();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<QuantityPoint QP>
|
|
||||||
[[nodiscard]] friend constexpr bool operator<=(const quantity_point& lhs, const QP& rhs)
|
|
||||||
requires std::totally_ordered_with<quantity_type, typename QP::quantity_type>
|
|
||||||
{
|
|
||||||
return !(rhs < lhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<QuantityPoint QP>
|
|
||||||
[[nodiscard]] friend constexpr bool operator>(const quantity_point& lhs, const QP& rhs)
|
|
||||||
requires std::totally_ordered_with<quantity_type, typename QP::quantity_type>
|
|
||||||
{
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<QuantityPoint QP>
|
|
||||||
[[nodiscard]] friend constexpr bool operator>=(const quantity_point& lhs, const QP& rhs)
|
|
||||||
requires std::totally_ordered_with<quantity_type, typename QP::quantity_type>
|
|
||||||
{
|
|
||||||
return !(lhs < rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename D, typename U, typename Rep>
|
template<typename D, typename U, typename Rep>
|
||||||
quantity_point(quantity<D, U, Rep>) -> quantity_point<D, U, Rep>;
|
quantity_point(quantity<D, U, Rep>) -> quantity_point<D, U, Rep>;
|
||||||
|
|
||||||
template<QuantityPoint QP, Quantity Q>
|
|
||||||
[[nodiscard]] constexpr QuantityPoint AUTO operator+(const QP& lhs, const Q& rhs)
|
|
||||||
requires requires { lhs.relative() + rhs; }
|
|
||||||
{
|
|
||||||
return quantity_point(lhs.relative() + rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<Quantity Q, QuantityPoint QP>
|
|
||||||
[[nodiscard]] constexpr QuantityPoint AUTO operator+(const Q& lhs, const QP& rhs)
|
|
||||||
requires requires { rhs + lhs; }
|
|
||||||
{
|
|
||||||
return rhs + lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<QuantityPoint QP, Quantity Q>
|
|
||||||
[[nodiscard]] constexpr QuantityPoint AUTO operator-(const QP& lhs, const Q& rhs)
|
|
||||||
requires requires { lhs.relative() - rhs; }
|
|
||||||
{
|
|
||||||
return quantity_point(lhs.relative() - rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<QuantityPoint QP1, QuantityPoint QP2>
|
|
||||||
[[nodiscard]] constexpr Quantity AUTO operator-(const QP1& lhs, const QP2& rhs)
|
|
||||||
requires requires { lhs.relative() - rhs.relative(); }
|
|
||||||
{
|
|
||||||
return lhs.relative() - rhs.relative();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<typename D, typename U, typename Rep>
|
template<typename D, typename U, typename Rep>
|
||||||
|
@ -55,24 +55,8 @@ struct ratio {
|
|||||||
detail::normalize(num, den, exp);
|
detail::normalize(num, den, exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator==(const ratio&, const ratio&) = default;
|
[[nodiscard]] friend constexpr bool operator==(const ratio&, const ratio&) = default;
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator==(const ratio& lhs, const ratio& rhs)
|
|
||||||
{
|
|
||||||
return lhs.num == rhs.num && lhs.den == rhs.den && lhs.exp == rhs.exp;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator!=(const ratio& lhs, const ratio& rhs)
|
|
||||||
{
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr ratio operator*(const ratio& lhs, const ratio& rhs)
|
[[nodiscard]] friend constexpr ratio operator*(const ratio& lhs, const ratio& rhs)
|
||||||
{
|
{
|
||||||
const std::intmax_t gcd1 = std::gcd(lhs.num, rhs.den);
|
const std::intmax_t gcd1 = std::gcd(lhs.num, rhs.den);
|
||||||
|
@ -25,10 +25,7 @@
|
|||||||
#include <units/bits/external/fixed_string.h>
|
#include <units/bits/external/fixed_string.h>
|
||||||
#include <units/bits/external/hacks.h>
|
#include <units/bits/external/hacks.h>
|
||||||
#include <gsl/gsl_assert>
|
#include <gsl/gsl_assert>
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
#include <compare>
|
#include <compare>
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
@ -125,8 +122,6 @@ struct basic_symbol_text {
|
|||||||
return basic_symbol_text<StandardCharT, 1, 1>(lhs) + rhs;
|
return basic_symbol_text<StandardCharT, 1, 1>(lhs) + rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if COMP_MSVC || COMP_GCC >= 10
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2, std::size_t M2>
|
template<typename StandardCharT2, std::size_t N2, std::size_t M2>
|
||||||
[[nodiscard]] friend constexpr auto operator<=>(const basic_symbol_text& lhs,
|
[[nodiscard]] friend constexpr auto operator<=>(const basic_symbol_text& lhs,
|
||||||
const basic_symbol_text<StandardCharT2, N2, M2>& rhs) noexcept
|
const basic_symbol_text<StandardCharT2, N2, M2>& rhs) noexcept
|
||||||
@ -141,217 +136,6 @@ struct basic_symbol_text {
|
|||||||
{
|
{
|
||||||
return lhs.standard() == rhs.standard() && lhs.ascii() == rhs.ascii();
|
return lhs.standard() == rhs.standard() && lhs.ascii() == rhs.ascii();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// I did not update the below operators with comparing ASCII as this code is going to be deleted soon anyway...
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2, std::size_t M2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(const basic_symbol_text& lhs,
|
|
||||||
const basic_symbol_text<StandardCharT2, N2, M2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs.standard() == rhs.standard();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2, std::size_t M2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator!=(const basic_symbol_text& lhs,
|
|
||||||
const basic_symbol_text<StandardCharT2, N2, M2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(const basic_symbol_text& lhs,
|
|
||||||
const basic_fixed_string<StandardCharT, N>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs.standard() == rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator!=(const basic_symbol_text& lhs,
|
|
||||||
const basic_fixed_string<StandardCharT, N>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(const basic_symbol_text&,
|
|
||||||
const basic_fixed_string<StandardCharT2, N2>&) noexcept
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator!=(const basic_symbol_text&,
|
|
||||||
const basic_fixed_string<StandardCharT2, N2>&) noexcept
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(const basic_symbol_text& lhs,
|
|
||||||
const StandardCharT (&rhs)[N + 1]) noexcept
|
|
||||||
{
|
|
||||||
return lhs.standard() == rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator!=(const basic_symbol_text& lhs,
|
|
||||||
const StandardCharT (&rhs)[N + 1]) noexcept
|
|
||||||
{
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(const basic_symbol_text&,
|
|
||||||
const StandardCharT2 (&)[N2 + 1]) noexcept
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator!=(const basic_symbol_text&,
|
|
||||||
const StandardCharT2 (&)[N2 + 1]) noexcept
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(const basic_symbol_text& lhs,
|
|
||||||
StandardCharT rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs.standard() == rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator!=(const basic_symbol_text& lhs,
|
|
||||||
StandardCharT rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(lhs == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(const basic_symbol_text&,
|
|
||||||
StandardCharT2) noexcept
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator!=(const basic_symbol_text&,
|
|
||||||
StandardCharT2) noexcept
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2, std::size_t M2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator<(const basic_symbol_text& lhs,
|
|
||||||
const basic_symbol_text<StandardCharT2, N2, M2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs.standard() < rhs.standard();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator<(const basic_symbol_text& lhs,
|
|
||||||
const basic_fixed_string<StandardCharT2, N2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs.standard() < rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator<(const basic_symbol_text& lhs,
|
|
||||||
const StandardCharT2 (&rhs)[N2]) noexcept
|
|
||||||
{
|
|
||||||
return lhs.standard() < basic_fixed_string(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator<(const basic_symbol_text& lhs,
|
|
||||||
StandardCharT2 rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs.standard() < basic_fixed_string(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2, std::size_t M2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator>(const basic_symbol_text& lhs,
|
|
||||||
const basic_symbol_text<StandardCharT2, N2, M2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator>(const basic_symbol_text& lhs,
|
|
||||||
const basic_fixed_string<StandardCharT2, N2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator>(const basic_symbol_text& lhs,
|
|
||||||
const StandardCharT2 (&rhs)[N2]) noexcept
|
|
||||||
{
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator>(const basic_symbol_text& lhs,
|
|
||||||
StandardCharT2 rhs) noexcept
|
|
||||||
{
|
|
||||||
return rhs < lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2, std::size_t M2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator<=(const basic_symbol_text& lhs,
|
|
||||||
const basic_symbol_text<StandardCharT2, N2, M2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(rhs < lhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator<=(const basic_symbol_text& lhs,
|
|
||||||
const basic_fixed_string<StandardCharT2, N2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(rhs < lhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator<=(const basic_symbol_text& lhs,
|
|
||||||
const StandardCharT2 (&rhs)[N2]) noexcept
|
|
||||||
{
|
|
||||||
return !(rhs < lhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator<=(const basic_symbol_text& lhs,
|
|
||||||
StandardCharT2 rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(rhs < lhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2, std::size_t M2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator>=(const basic_symbol_text& lhs,
|
|
||||||
const basic_symbol_text<StandardCharT2, N2, M2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(lhs < rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator>=(const basic_symbol_text& lhs,
|
|
||||||
const basic_fixed_string<StandardCharT2, N2>& rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(lhs < rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2, std::size_t N2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator>=(const basic_symbol_text& lhs,
|
|
||||||
const StandardCharT2 (&rhs)[N2]) noexcept
|
|
||||||
{
|
|
||||||
return !(lhs < rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename StandardCharT2>
|
|
||||||
[[nodiscard]] constexpr friend bool operator>=(const basic_symbol_text& lhs,
|
|
||||||
StandardCharT2 rhs) noexcept
|
|
||||||
{
|
|
||||||
return !(lhs < rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
basic_symbol_text(char) -> basic_symbol_text<char, 1, 1>;
|
basic_symbol_text(char) -> basic_symbol_text<char, 1, 1>;
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
using namespace units::physical;
|
using namespace units::physical;
|
||||||
|
|
||||||
constexpr Speed AUTO avg_speed(Length AUTO d, Time AUTO t)
|
constexpr Speed auto avg_speed(Length auto d, Time auto t)
|
||||||
{
|
{
|
||||||
return d / t;
|
return d / t;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user