based

Opinionated utility library
git clone git://git.dimitrijedobrota.com/based.git
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

commitd0cad211ce8712dd5488edf4a8b5279d1b3860db
parent0bc4b5da4aea6b51681aeaea21ddffcfe87b9510
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateSun, 6 Apr 2025 19:29:54 +0200

Add more concepts to ease domain management

Diffstat:
Minclude/based/algorithm.hpp|++++++++++++++----------------------------
Minclude/based/functional.hpp|+++++----------
Minclude/based/type_traits.hpp|+++++++++++++++++++++++++++++++++++++++

3 files changed, 58 insertions(+), 38 deletions(-)


diff --git a/include/based/algorithm.hpp b/include/based/algorithm.hpp

@@ -27,8 +27,7 @@ decltype(auto) min(T&& lhs, U&& rhs)

}
// return first min element
template<Iterator I, Relation R>
requires SameAs<iter_value_t<I>, domain_t<R>>
template<Iterator I, IterRelation<I> R>
I min_element(I first, I last, R r)
{
if (first == last) {

@@ -69,8 +68,7 @@ decltype(auto) max(T&& lhs, U&& rhs)

}
// return last max element
template<Iterator I, Relation R>
requires std::same_as<iter_value_t<I>, domain_t<R>>
template<Iterator I, IterRelation<I> R>
I max_element(I first, I last, R r)
{
if (first == last) {

@@ -94,8 +92,7 @@ I max_element(I first, I last)

}
// return first min and last max element
template<Iterator I, Relation R>
requires std::same_as<iter_value_t<I>, domain_t<R>>
template<Iterator I, IterRelation<I> R>
std::pair<I, I> minmax_element(I first, I last, R r)
{
if (first == last) {

@@ -151,8 +148,7 @@ std::pair<I, I> minmax_element(I first, I last)

return based::minmax_element(first, last, std::less<iter_value_t<I>>());
}
template<ReadableIterator I, UnaryProcedure Proc>
requires SameAs<iter_value_t<I>, domain_t<Proc>>
template<ReadableIterator I, IterUnaryProcedure<I> Proc>
Proc for_each(I f, I d, Proc proc)
{
// Precondition: readable_bounded_range(f, d);

@@ -183,8 +179,7 @@ I find_not(I f, I d, const iter_value_t<I>& x)

return f;
}
template<ReadableIterator I, UnaryPredicate P>
requires SameAs<iter_value_t<I>, domain_t<P>>
template<ReadableIterator I, IterUnaryPredicate<I> P>
I find_if(I f, I d, P p)
{
// Precondition: readable_bounded_range(f, d);

@@ -194,8 +189,7 @@ I find_if(I f, I d, P p)

return f;
}
template<ReadableIterator I, UnaryPredicate P>
requires SameAs<iter_value_t<I>, domain_t<P>>
template<ReadableIterator I, IterUnaryPredicate<I> P>
I find_if_not(I f, I d, P p)
{
// Precondition: readable_bounded_range(f, d);

@@ -205,32 +199,28 @@ I find_if_not(I f, I d, P p)

return f;
}
template<ReadableIterator I, UnaryPredicate P>
requires SameAs<iter_value_t<I>, domain_t<P>>
template<ReadableIterator I, IterUnaryPredicate<I> P>
bool all(I f, I d, P p)
{
// Precondition: readable_bounded_range(f, d);
return find_if_not(f, d, p) == d;
}
template<ReadableIterator I, UnaryPredicate P>
requires SameAs<iter_value_t<I>, domain_t<P>>
template<ReadableIterator I, IterUnaryPredicate<I> P>
bool none(I f, I d, P p)
{
// Precondition: readable_bounded_range(f, d);
return find_if(f, d, p) == d;
}
template<ReadableIterator I, UnaryPredicate P>
requires SameAs<iter_value_t<I>, domain_t<P>>
template<ReadableIterator I, IterUnaryPredicate<I> P>
bool not_all(I f, I d, P p)
{
// Precondition: readable_bounded_range(f, d);
return f == d || find_if_not(f, d, p) != d;
}
template<ReadableIterator I, UnaryPredicate P>
requires SameAs<iter_value_t<I>, domain_t<P>>
template<ReadableIterator I, IterUnaryPredicate<I> P>
bool some(I f, I d, P p)
{
// Precondition: readable_bounded_range(f, d);

@@ -276,8 +266,7 @@ iter_dist_t<I> count_not(I f, I d, const iter_value_t<I>& x)

return count_not(f, d, x, iter_dist_t<I> {0});
}
template<ReadableIterator I, UnaryPredicate P, Iterator J>
requires SameAs<iter_value_t<I>, domain_t<P>>
template<ReadableIterator I, IterUnaryPredicate<I> P, Iterator J>
J count_if(I f, I d, P p, J j)
{
// Precondition: readable_bounded_range(f, d);

@@ -290,16 +279,14 @@ J count_if(I f, I d, P p, J j)

return j;
}
template<ReadableIterator I, UnaryPredicate P>
requires SameAs<iter_value_t<I>, domain_t<P>>
template<ReadableIterator I, IterUnaryPredicate<I> P>
iter_dist_t<I> count_if(I f, I d, P p)
{
// Precondition: readable_bounded_range(f, d);
return count_if(f, d, p, iter_dist_t<I> {0});
}
template<ReadableIterator I, UnaryPredicate P, Iterator J>
requires SameAs<iter_value_t<I>, domain_t<P>>
template<ReadableIterator I, IterUnaryPredicate<I> P, Iterator J>
J count_if_not(I f, I d, P p, J j)
{
// Precondition: readable_bounded_range(f, d);

@@ -312,8 +299,7 @@ J count_if_not(I f, I d, P p, J j)

return j;
}
template<ReadableIterator I, UnaryPredicate P>
requires SameAs<iter_value_t<I>, domain_t<P>>
template<ReadableIterator I, IterUnaryPredicate<I> P>
iter_dist_t<I> count_if_not(I f, I d, P p)
{
// Precondition: readable_bounded_range(f, d);

diff --git a/include/based/functional.hpp b/include/based/functional.hpp

@@ -32,8 +32,7 @@ domain_t<F> convergant_point(domain_t<F> x0, domain_t<F> x1, F f)

return x0;
}
template<Transformation F, UnaryPredicate P>
requires SameAs<domain_t<F>, domain_t<P>>
template<Transformation F, TransformUnaryPredicate<F> P>
domain_t<F> collision_point(const domain_t<F>& x, F f, P p)
{
// Precondition p(x) <=> f(x) is defined

@@ -58,16 +57,14 @@ domain_t<F> collision_point(const domain_t<F>& x, F f, P p)

// Postcondition: return value is terminal point or collision point
}
template<Transformation F, UnaryPredicate P>
requires SameAs<domain_t<F>, domain_t<P>>
template<Transformation F, TransformUnaryPredicate<F> P>
bool terminating(const domain_t<F>& x, F f, P p)
{
// Precondition: p(x) <=> F(x) is defined
return !p(collision_point(x, f, p));
}
template<Transformation F, UnaryPredicate P>
requires SameAs<domain_t<F>, domain_t<P>>
template<Transformation F, TransformUnaryPredicate<F> P>
bool circular(const domain_t<F>& x, F f, P p)
{
// Precondition: p(x) <=> F(x) is defined

@@ -75,8 +72,7 @@ bool circular(const domain_t<F>& x, F f, P p)

return p(y) && x == f(y);
}
template<Transformation F, UnaryPredicate P>
requires SameAs<domain_t<F>, domain_t<P>>
template<Transformation F, TransformUnaryPredicate<F> P>
bool connection_point(const domain_t<F>& x, F f, P p)
{
// Precondition: p(x) <=> F(x) is defined

@@ -87,8 +83,7 @@ bool connection_point(const domain_t<F>& x, F f, P p)

return convergant_point(x, f(y), f);
}
template<Transformation F, UnaryPredicate P>
requires SameAs<domain_t<F>, domain_t<P>>
template<Transformation F, TransformUnaryPredicate<F> P>
std::tuple<distance_t<F>, distance_t<F>, domain_t<F>> orbit_structure(
const domain_t<F>& x, F f, P p)
{

diff --git a/include/based/type_traits.hpp b/include/based/type_traits.hpp

@@ -386,6 +386,45 @@ concept Relation = requires {

requires(arity_v<P> == 2);
};
/* ----- Iterator variants ----- */
template<typename P, typename I>
concept IterUnaryProcedure = requires {
requires(UnaryProcedure<P>);
requires(Iterator<I>);
requires(SameAs<iter_value_t<I>, domain_t<P>>);
};
template<typename P, typename I>
concept IterUnaryFunction = requires {
requires(UnaryFunction<P>);
requires(Iterator<I>);
requires(SameAs<iter_value_t<I>, domain_t<P>>);
};
template<typename P, typename I>
concept IterUnaryPredicate = requires {
requires(UnaryPredicate<P>);
requires(Iterator<I>);
requires(SameAs<iter_value_t<I>, domain_t<P>>);
};
template<typename P, typename I>
concept IterRelation = requires {
requires(Relation<P>);
requires(Iterator<I>);
requires(SameAs<iter_value_t<I>, domain_t<P>>);
};
/* ----- Transformation Variant ----- */
template<typename P, typename T>
concept TransformUnaryPredicate = requires {
requires(UnaryPredicate<P>);
requires(Transformation<T>);
requires(SameAs<domain_t<T>, domain_t<P>>);
};
/* ----- Abstract Algebra ----- */
// clang-format off