forked from mpusz/mp-units
quantity constraints refactored
This commit is contained in:
@@ -23,51 +23,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <units/bits/hacks.h>
|
||||
#include <units/bits/numeric_concepts.h>
|
||||
#include <units/bits/customization_points.h>
|
||||
#include <units/ratio.h>
|
||||
|
||||
namespace units {
|
||||
|
||||
#if __GNUC__ < 10
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
concept Number = std::regular<T> &&
|
||||
std::totally_ordered<T> &&
|
||||
requires(T a, T b) {
|
||||
{ a + b } -> T;
|
||||
{ a - b } -> T;
|
||||
{ a * b } -> T;
|
||||
{ a / b } -> T;
|
||||
{ +a } -> T;
|
||||
{ -a } -> T;
|
||||
{ a += b } -> T&;
|
||||
{ a -= b } -> T&;
|
||||
{ a *= b } -> T&;
|
||||
{ a /= b } -> T&;
|
||||
{ T{0} }; // can construct a T from a zero
|
||||
// …
|
||||
};
|
||||
template<typename T, typename U = T>
|
||||
concept basic_arithmetic = // exposition only
|
||||
std::magma<std::ranges::plus, T, U> &&
|
||||
std::magma<std::ranges::minus, T, U> &&
|
||||
std::magma<std::ranges::times, T, U> &&
|
||||
std::magma<std::ranges::divided_by, T, U>;
|
||||
|
||||
#else
|
||||
template<typename From, typename To>
|
||||
concept safe_convertible = // exposition only
|
||||
std::convertible_to<From, To> &&
|
||||
(treat_as_floating_point<To> || (!treat_as_floating_point<From>));
|
||||
|
||||
template<typename T>
|
||||
concept Number = std::regular<T> &&
|
||||
std::totally_ordered<T> &&
|
||||
requires(T a, T b) {
|
||||
{ a + b } -> std::same_as<T>;
|
||||
{ a - b } -> std::same_as<T>;
|
||||
{ a * b } -> std::same_as<T>;
|
||||
{ a / b } -> std::same_as<T>;
|
||||
{ +a } -> std::same_as<T>;
|
||||
{ -a } -> std::same_as<T>;
|
||||
{ a += b } -> std::same_as<T&>;
|
||||
{ a -= b } -> std::same_as<T&>;
|
||||
{ a *= b } -> std::same_as<T&>;
|
||||
{ a /= b } -> std::same_as<T&>;
|
||||
{ T{0} }; // can construct a T from a zero
|
||||
// …
|
||||
};
|
||||
template<typename Rep, typename unit_from, typename unit_to>
|
||||
concept safe_divisible = // exposition only
|
||||
treat_as_floating_point<Rep> ||
|
||||
ratio_divide<typename unit_from::ratio, typename unit_to::ratio>::den == 1;
|
||||
|
||||
#endif
|
||||
|
||||
// InstanceOf
|
||||
}
|
||||
|
||||
} // namespace units
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <concepts/concepts.hpp>
|
||||
#include <functional>
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define Expects(cond) (void)(cond);
|
||||
@@ -33,17 +34,34 @@
|
||||
|
||||
#if __GNUC__ > 9
|
||||
#define AUTO auto
|
||||
#define SAME_AS(T) std::same_as<T>
|
||||
#else
|
||||
#define AUTO
|
||||
#define SAME_AS(T) T
|
||||
#endif
|
||||
|
||||
namespace std {
|
||||
|
||||
// concepts
|
||||
using concepts::same_as;
|
||||
using concepts::derived_from;
|
||||
using concepts::regular;
|
||||
using concepts::totally_ordered;
|
||||
using concepts::common_with;
|
||||
using concepts::common_reference_with;
|
||||
using concepts::constructible_from;
|
||||
using concepts::convertible_to;
|
||||
using concepts::default_constructible;
|
||||
using concepts::derived_from;
|
||||
using concepts::equality_comparable_with;
|
||||
using concepts::regular;
|
||||
using concepts::same_as;
|
||||
using concepts::totally_ordered;
|
||||
using concepts::totally_ordered_with;
|
||||
|
||||
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...>;
|
||||
|
||||
}
|
||||
|
||||
@@ -117,14 +117,14 @@ namespace std {
|
||||
|
||||
template<class BOp, class T, class U>
|
||||
concept magma =
|
||||
std::common_with<T, U> &&
|
||||
std::regular_invocable<BOp, T, T> &&
|
||||
std::regular_invocable<BOp, U, U> &&
|
||||
std::regular_invocable<BOp, T, U> &&
|
||||
std::regular_invocable<BOp, U, T> &&
|
||||
std::common_with<std::invoke_result_t<BOp&, T, U>, T> &&
|
||||
std::common_with<std::invoke_result_t<BOp&, T, U>, U> &&
|
||||
std::same_as<std::invoke_result_t<BOp&, T, U>, std::invoke_result_t<BOp&, U, T>>;
|
||||
common_with<T, U> &&
|
||||
regular_invocable<BOp, T, T> &&
|
||||
regular_invocable<BOp, U, U> &&
|
||||
regular_invocable<BOp, T, U> &&
|
||||
regular_invocable<BOp, U, T> &&
|
||||
common_with<invoke_result_t<BOp&, T, U>, T> &&
|
||||
common_with<invoke_result_t<BOp&, T, U>, U> &&
|
||||
same_as<invoke_result_t<BOp&, T, U>, invoke_result_t<BOp&, U, T>>;
|
||||
|
||||
template<class BOp, class T, class U>
|
||||
concept semigroup = magma<BOp, T, U>;
|
||||
@@ -166,7 +166,6 @@ namespace std {
|
||||
};
|
||||
|
||||
|
||||
|
||||
namespace ranges {
|
||||
|
||||
namespace detail {
|
||||
@@ -200,7 +199,7 @@ namespace std {
|
||||
|
||||
template<class T>
|
||||
concept negatable = // exposition only
|
||||
summable_with <T, T> &&
|
||||
summable_with<T, T> &&
|
||||
totally_ordered<T> &&
|
||||
requires(T&& t) {
|
||||
{ -std::forward<T>(t) } -> common_with<T>;
|
||||
@@ -231,7 +230,7 @@ namespace std {
|
||||
{ std::forward<T>(t) - std::forward<U>(u) } -> common_with<T>;
|
||||
{ std::forward<U>(u) - std::forward<T>(t) } -> common_with<U>;
|
||||
requires same_as<decltype(std::forward<T>(t) - std::forward<U>(u)),
|
||||
decltype(std::forward<U>(u) - std::forward<T>(t))>;
|
||||
decltype(std::forward<U>(u) - std::forward<T>(t))>;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -249,10 +248,10 @@ namespace std {
|
||||
|
||||
template<class T, class U>
|
||||
concept multiplicable_with = // exposition only
|
||||
detail::summable_with <T, U> &&
|
||||
detail::summable_with<T, U> &&
|
||||
constructible_from<remove_cvref_t<T>, int> && // specifically T{0} and T{1}
|
||||
constructible_from<remove_cvref_t<U>, int> && // specifically U{0} and U{1}
|
||||
constructible_from<remove_cvref_t<common_type<T, U>>, int> &&
|
||||
// constructible_from<remove_cvref_t<common_type<T, U>>, int> && // TODO uncomment this when the problem is resolved
|
||||
common_reference_with<T, U> &&
|
||||
requires(T&& t, U&& u) {
|
||||
{ std::forward<T>(t) * std::forward<T>(t) } -> common_with<T>;
|
||||
@@ -260,7 +259,7 @@ namespace std {
|
||||
{ std::forward<T>(t) * std::forward<U>(u) } -> common_with<T>;
|
||||
{ std::forward<U>(u) * std::forward<T>(t) } -> common_with<U>;
|
||||
requires same_as<decltype(std::forward<T>(t) * std::forward<U>(u)),
|
||||
decltype(std::forward<U>(u) * std::forward<T>(t))>;
|
||||
decltype(std::forward<U>(u) * std::forward<T>(t))>;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -285,7 +284,7 @@ namespace std {
|
||||
{ std::forward<T>(t) / std::forward<U>(u) } -> common_with<T>;
|
||||
{ std::forward<U>(u) / std::forward<T>(t) } -> common_with<U>;
|
||||
requires same_as<decltype(std::forward<T>(t) / std::forward<U>(u)),
|
||||
decltype(std::forward<U>(u) / std::forward<T>(t))>;
|
||||
decltype(std::forward<U>(u) / std::forward<T>(t))>;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -300,14 +299,14 @@ namespace std {
|
||||
|
||||
template<class T, class Q>
|
||||
concept modulo_with = // exposition only
|
||||
divisible_with <T, Q> &&
|
||||
divisible_with<T, Q> &&
|
||||
requires(T&& t, Q&& q) {
|
||||
{ std::forward<T>(t) % std::forward<T>(t) } -> common_with<T>;
|
||||
{ std::forward<Q>(q) % std::forward<Q>(q) } -> common_with<Q>;
|
||||
{ std::forward<T>(t) % std::forward<Q>(q) } -> common_with<T>;
|
||||
{ std::forward<Q>(q) % std::forward<T>(t) } -> common_with<Q>;
|
||||
requires same_as<decltype(std::forward<T>(t) % std::forward<Q>(q)),
|
||||
decltype(std::forward<Q>(q) % std::forward<T>(t))>;
|
||||
decltype(std::forward<Q>(q) % std::forward<T>(t))>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user