quantity constraints refactored

This commit is contained in:
Mateusz Pusz
2019-11-15 20:20:25 +01:00
parent 2b5eb30cd4
commit 57e464cc99
6 changed files with 241 additions and 145 deletions
+19 -39
View File
@@ -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
+22 -4
View File
@@ -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...>;
}
+16 -17
View File
@@ -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))>;
};
}