refactor: got rid of gcc-9 backlog

BREAKING CHANGE: gcc-9.3 no longer supported
This commit is contained in:
Mateusz Pusz
2020-09-08 13:09:34 +02:00
parent 7ed4f19ef3
commit 4bb51586dc
27 changed files with 131 additions and 760 deletions
-8
View File
@@ -76,16 +76,8 @@ using common_quantity_point = decltype(
} // namespace units
#if COMP_MSVC || COMP_GCC >= 10
namespace std {
#else
namespace concepts {
#endif
template<units::Quantity Q1, units::Quantity Q2>
requires units::equivalent_dim<typename Q1::dimension, typename Q2::dimension>
struct common_type<Q1, Q2> {
-73
View File
@@ -26,10 +26,7 @@
#include <algorithm>
#include <cstdlib>
#include <ostream>
#if COMP_MSVC || COMP_GCC >= 10
#include <compare>
#endif
namespace units {
@@ -76,8 +73,6 @@ struct basic_fixed_string {
return basic_fixed_string<CharT, N + N2>(txt);
}
#if COMP_MSVC || COMP_GCC >= 10
[[nodiscard]] constexpr bool operator==(const basic_fixed_string& other) const
{
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());
}
#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>
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os,
const basic_fixed_string& txt)
+7 -70
View File
@@ -22,7 +22,7 @@
#pragma once
#include <functional>
#include <concepts>
#if __clang__
#define COMP_CLANG __clang_major__
@@ -33,29 +33,6 @@
#define COMP_MSVC _MSC_VER
#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
#define TYPENAME typename
@@ -66,53 +43,13 @@
#endif
#if COMP_GCC
namespace std {
#if COMP_GCC
#if COMP_GCC >= 10
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
template<class T>
concept default_constructible = constructible_from<T>;
} // namespace std
#endif
+1
View File
@@ -27,6 +27,7 @@
#include <units/bits/external/hacks.h>
#include <units/ratio.h>
#include <units/bits/external/type_traits.h>
#include <functional>
namespace units {
+4 -4
View File
@@ -40,7 +40,7 @@ namespace units {
*/
template<std::intmax_t N, Quantity Q>
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); }
{
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
*/
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()); }
{
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
*/
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()); }
{
return Q(std::abs(q.count()));
@@ -115,7 +115,7 @@ inline Quantity AUTO abs(const Q& q) noexcept
*/
template<Quantity Q>
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());
}
+26 -107
View File
@@ -29,11 +29,7 @@
#include <units/bits/to_string.h>
#include <units/dimensionless.h>
#include <units/quantity_cast.h>
#if COMP_MSVC || COMP_GCC >= 10
#include <compare>
#endif
#include <ostream>
namespace units {
@@ -90,78 +86,60 @@ public:
[[nodiscard]] constexpr rep count() const noexcept { return value_; }
template<typename T = Rep>
[[nodiscard]] static constexpr quantity zero() noexcept
requires requires { quantity_values<T>::zero(); }
// requires requires { quantity_values<Rep>::zero(); } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires { quantity_values<Rep>::zero(); }
{
return quantity(quantity_values<Rep>::zero());
}
template<typename T = Rep>
[[nodiscard]] static constexpr quantity one() noexcept
requires requires { quantity_values<T>::one(); }
// requires requires { quantity_values<Rep>::one(); } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires { quantity_values<Rep>::one(); }
{
return quantity(quantity_values<Rep>::one());
}
template<typename T = Rep>
[[nodiscard]] static constexpr quantity min() noexcept
requires requires { quantity_values<T>::min(); }
// requires requires { quantity_values<Rep>::min(); } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires { quantity_values<Rep>::min(); }
{
return quantity(quantity_values<Rep>::min());
}
template<typename T = Rep>
[[nodiscard]] static constexpr quantity max() noexcept
requires requires { quantity_values<T>::max(); }
// requires requires { quantity_values<Rep>::max(); } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires { quantity_values<Rep>::max(); }
{
return quantity(quantity_values<Rep>::max());
}
[[nodiscard]] constexpr quantity operator+() const { return *this; }
template<typename T = Rep>
[[nodiscard]] constexpr quantity operator-() const
requires std::regular_invocable<std::negate<>, T>
// requires std::regular_invocable<std::negate<>, rep> // TODO gated by gcc-9 (fixed in gcc-10)
requires std::regular_invocable<std::negate<>, rep>
{
return quantity(-count());
}
template<typename T = Rep>
constexpr quantity& operator++()
requires requires(T v) { { ++v } -> SAME_AS(T&); }
// requires requires(rep v) { { ++v } -> std::same_as<rep&>; } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires(rep v) { { ++v } -> std::same_as<rep&>; }
{
++value_;
return *this;
}
template<typename T = Rep>
[[nodiscard]] constexpr quantity operator++(int)
requires requires(T v) { { v++ } -> SAME_AS(T); }
// requires requires(rep v) { { v++ } -> std::same_as<rep>; } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires(rep v) { { v++ } -> std::same_as<rep>; }
{
return quantity(value_++);
}
template<typename T = Rep>
constexpr quantity& operator--()
requires requires(T v) { { --v } -> SAME_AS(T&); }
// requires requires(rep v) { { --v } -> std::same_as<rep&>; } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires(rep v) { { --v } -> std::same_as<rep&>; }
{
--value_;
return *this;
}
template<typename T = Rep>
[[nodiscard]] constexpr quantity operator--(int)
requires requires(T v) { { v-- } -> SAME_AS(T); }
// requires requires(rep v) { { v-- } -> std::same_as<rep>; } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires(rep v) { { v-- } -> std::same_as<rep>; }
{
return quantity(value_--);
}
@@ -198,22 +176,19 @@ public:
return *this;
}
template<Scalar Value, typename T = Rep>
constexpr quantity& operator%=(const Value& rhs)
template<Scalar Value>
requires (!treat_as_floating_point<rep>) &&
(!treat_as_floating_point<Value>) &&
requires(T v1, Value v2) { { v1 %= v2 } -> SAME_AS(T&); }
// requires(rep v1, Value v2) { { v1 %= v2 } -> SAME_AS(rep&); } // TODO gated by gcc-9 (fixed in gcc-10)
(!treat_as_floating_point<Value>)
constexpr quantity& operator%=(const Value& rhs)
requires requires(rep v1, Value v2) { { v1 %= v2 } -> std::same_as<rep&>; }
{
value_ %= rhs;
return *this;
}
template<typename T = Rep>
constexpr quantity& operator%=(const quantity& q)
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&>; } // TODO gated by gcc-9 (fixed in gcc-10)
requires(rep v1, rep v2) { { v1 %= v2 } -> std::same_as<rep&>; }
{
value_ %= q.count();
return *this;
@@ -229,8 +204,8 @@ public:
}
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>
[[nodiscard]] friend constexpr Quantity auto operator+(const quantity& lhs, const quantity<D, U2, Rep2>& rhs)
{
using common_rep = decltype(lhs.count() + rhs.count());
using ret = common_quantity<quantity, quantity<D, U2, Rep2>, common_rep>;
@@ -244,8 +219,8 @@ public:
}
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>
[[nodiscard]] friend constexpr Quantity auto operator-(const quantity& lhs, const quantity<D, U2, Rep2>& rhs)
{
using common_rep = decltype(lhs.count() - rhs.count());
using ret = common_quantity<quantity, quantity<D, U2, Rep2>, common_rep>;
@@ -253,8 +228,8 @@ public:
}
template<Scalar Value>
[[nodiscard]] friend constexpr Quantity AUTO operator*(const quantity& q, const Value& v)
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 ret = quantity<D, U, common_rep>;
@@ -262,15 +237,15 @@ public:
}
template<Scalar Value>
[[nodiscard]] friend constexpr Quantity AUTO operator*(const Value& v, const quantity& q)
requires std::regular_invocable<std::multiplies<>, Value, Rep>
[[nodiscard]] friend constexpr Quantity auto operator*(const Value& v, const quantity& q)
{
return q * v;
}
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>
[[nodiscard]] friend constexpr Quantity auto operator*(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
{
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>;
@@ -280,8 +255,8 @@ public:
}
template<Scalar Value>
[[nodiscard]] friend constexpr Quantity AUTO operator/(const Value& v, const quantity& q)
requires std::regular_invocable<std::divides<>, Value, Rep>
[[nodiscard]] friend constexpr Quantity auto operator/(const Value& v, const quantity& q)
{
Expects(q.count() != 0);
@@ -293,8 +268,8 @@ public:
}
template<Scalar Value>
[[nodiscard]] friend constexpr Quantity AUTO operator/(const quantity& q, const Value& v)
requires std::regular_invocable<std::divides<>, Rep, Value>
[[nodiscard]] friend constexpr Quantity auto operator/(const quantity& q, const Value& v)
{
Expects(v != Value{0});
@@ -304,8 +279,8 @@ public:
}
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>
[[nodiscard]] friend constexpr Quantity auto operator/(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
{
Expects(rhs.count() != 0);
@@ -317,10 +292,10 @@ public:
}
template<Scalar Value>
[[nodiscard]] friend constexpr Quantity AUTO operator%(const quantity& q, const Value& v)
requires (!treat_as_floating_point<Rep>) &&
(!treat_as_floating_point<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 ret = quantity<D, U, common_rep>;
@@ -328,90 +303,34 @@ public:
}
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>) &&
(!treat_as_floating_point<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 ret = common_quantity<quantity, quantity<D, U2, Rep2>, common_rep>;
return ret(ret(lhs).count() % ret(rhs).count());
}
#if COMP_MSVC || COMP_GCC >= 10
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> &&
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>>;
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>
[[nodiscard]] friend constexpr bool operator==(const quantity& lhs, const quantity<D2, U2, Rep2>& rhs)
{
using cq = common_quantity<quantity, quantity<D2, U2, Rep2>>;
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>
friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const quantity& q)
{
+4 -4
View File
@@ -313,8 +313,8 @@ constexpr ratio cast_ratio(const Q1& from, const Q2& to)
* @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>
[[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_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
*/
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>
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, 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
*/
template<Unit ToU, typename D, typename U, typename Rep>
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, Rep>& q)
requires UnitOf<ToU, D>
[[nodiscard]] constexpr auto quantity_cast(const quantity<D, U, 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
*/
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(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>)
return quantity_point(quantity_cast<typename CastSpec::quantity_type>(qp.relative()));
+42 -103
View File
@@ -24,10 +24,7 @@
#pragma once
#include <units/quantity.h>
#if COMP_MSVC || COMP_GCC >= 10
#include <compare>
#endif
namespace units {
@@ -69,69 +66,53 @@ public:
[[nodiscard]] constexpr quantity_type relative() const noexcept { return q_; }
template<typename Q = quantity_type>
[[nodiscard]] static constexpr quantity_point min() noexcept
requires requires { Q::min(); }
// requires requires { quantity_type::min(); } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires { quantity_type::min(); }
{
return quantity_point(quantity_type::min());
}
template<typename Q = quantity_type>
[[nodiscard]] static constexpr quantity_point max() noexcept
requires requires { Q::max(); }
// requires requires { quantity_type::max(); } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires { quantity_type::max(); }
{
return quantity_point(quantity_type::max());
}
template<typename Q = quantity_type>
requires requires(Q q) { ++q; }
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_;
return *this;
}
template<typename Q = quantity_type>
[[nodiscard]] constexpr quantity_point operator++(int)
requires requires(Q q) { q++; }
// requires requires(quantity_type q) { q++; } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires(quantity_type q) { q++; }
{
return quantity_point(q_++);
}
template<typename Q = quantity_type>
requires requires(Q q) { --q; }
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_;
return *this;
}
template<typename Q = quantity_type>
[[nodiscard]] constexpr quantity_point operator--(int)
requires requires(Q q) { q--; }
// requires requires(quantity_type q) { q--; } // TODO gated by gcc-9 (fixed in gcc-10)
requires requires(quantity_type q) { 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)
// 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;
return *this;
}
template<typename Q = quantity_type>
requires requires(Q q1, Q q2) { q1 -= q2; }
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;
return *this;
@@ -139,100 +120,58 @@ public:
// Hidden Friends
// 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>
[[nodiscard]] friend constexpr auto operator<=>(const quantity_point& lhs, const QP& rhs)
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();
}
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>
[[nodiscard]] friend constexpr bool operator==(const quantity_point& lhs, const QP& rhs)
{
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>
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 {
template<typename D, typename U, typename Rep>
-16
View File
@@ -55,24 +55,8 @@ struct ratio {
detail::normalize(num, den, exp);
}
#if COMP_MSVC || COMP_GCC >= 10
[[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)
{
const std::intmax_t gcd1 = std::gcd(lhs.num, rhs.den);
-216
View File
@@ -25,10 +25,7 @@
#include <units/bits/external/fixed_string.h>
#include <units/bits/external/hacks.h>
#include <gsl/gsl_assert>
#if COMP_MSVC || COMP_GCC >= 10
#include <compare>
#endif
namespace units {
@@ -125,8 +122,6 @@ struct basic_symbol_text {
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>
[[nodiscard]] friend constexpr auto operator<=>(const basic_symbol_text& lhs,
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();
}
#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>;