Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions include/meta/meta_fwd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,8 @@
#endif
#if __cpp_concepts <= 201507L
#define META_CONCEPT concept bool
// TS concepts subsumption barrier for atomic expressions
#define META_CONCEPT_BARRIER(...) ::meta::detail::bool_<__VA_ARGS__>
#else
#define META_CONCEPT concept
#define META_CONCEPT_BARRIER(...) __VA_ARGS__
#if __cpp_concepts >= 201811L
#define META_HAS_P1084
#endif
Expand Down Expand Up @@ -211,23 +208,20 @@ namespace meta
#ifdef META_CONCEPT
namespace detail
{
template <bool B>
META_INLINE_VAR constexpr bool bool_ = B;

template <auto> struct require_constant; // not defined
}

template <typename...>
META_CONCEPT True = META_CONCEPT_BARRIER(true);
META_CONCEPT True = true;

template <typename T, typename U>
META_CONCEPT Same =
#if defined(__clang__)
META_CONCEPT_BARRIER(__is_same(T, U));
__is_same(T, U);
#elif defined(__GNUC__) && __GNUC__ >= 6
META_CONCEPT_BARRIER(__is_same_as(T, U));
__is_same_as(T, U);
#else
META_CONCEPT_BARRIER(std::is_same_v<T, U>);
std::is_same_v<T, U>;
#endif

template <template <typename...> class C, typename... Ts>
Expand Down
3 changes: 1 addition & 2 deletions include/stl2/detail/algorithm/upper_bound.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ STL2_OPEN_NAMESPACE {
}

struct __upper_bound_fn : private __niebloid {
template<ForwardIterator I, Sentinel<I> S, class T,
class Proj = identity,
template<ForwardIterator I, Sentinel<I> S, class T, class Proj = identity,
IndirectStrictWeakOrder<const T*, projected<I, Proj>> Comp = less>
constexpr I operator()(I first, S last, const T& value,
Comp comp = {}, Proj proj = {}) const
Expand Down
3 changes: 2 additions & 1 deletion include/stl2/detail/cached_position.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define STL2_DETAIL_CACHED_POSITION_HPP

#include <stl2/detail/fwd.hpp>
#include <stl2/detail/meta.hpp>
#include <stl2/detail/swap.hpp>
#include <stl2/detail/non_propagating_cache.hpp>
#include <stl2/detail/iterator/operations.hpp>
Expand Down Expand Up @@ -62,7 +63,7 @@ STL2_OPEN_NAMESPACE {
cache_ = it;
}
private:
meta::if_c<_ForwardingRange<R>,
__cond<_ForwardingRange<R>,
std::optional<iterator_t<R>>,
non_propagating_cache<iterator_t<R>>> cache_;
};
Expand Down
61 changes: 0 additions & 61 deletions include/stl2/detail/cheap_storage.hpp

This file was deleted.

148 changes: 148 additions & 0 deletions include/stl2/detail/closure.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// cmcstl2 - A concept-enabled C++ standard library
//
// Copyright Eric Niebler 2017
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/caseycarter/cmcstl2
//
#ifndef STL2_DETAIL_CLOSURE_HPP
#define STL2_DETAIL_CLOSURE_HPP

#include <stl2/detail/fwd.hpp>
#include <stl2/detail/meta.hpp>
#include <stl2/detail/concepts/callable.hpp>

STL2_OPEN_NAMESPACE {
namespace detail {
struct __pipeable_base;

template<class T>
META_CONCEPT Pipeable =
DerivedFrom<T, __pipeable_base> && ext::CopyConstructibleObject<T>;

template<Pipeable, Pipeable>
struct __pipeline;

struct __pipeable_base {
template<Pipeable Left, Pipeable Right>
requires Constructible<__uncvref<Left>, Left> &&
Constructible<__uncvref<Right>, Right>
friend constexpr auto operator|(Left&& left, Right&& right)
{ return __pipeline{static_cast<Left&&>(left), static_cast<Right&&>(right)}; }
};

template<class Derived>
struct __pipeable : __pipeable_base {
template<class T>
friend constexpr auto operator|(T&& t, Derived& d)
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68093
-> decltype(d(static_cast<T&&>(t)))
{ return d(static_cast<T&&>(t)); }

template<class T>
friend constexpr auto operator|(T&& t, const Derived& d)
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68093
-> decltype(d(static_cast<T&&>(t)))
{ return d(static_cast<T&&>(t)); }

template<class T>
friend constexpr auto operator|(T&& t, Derived&& d)
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68093
-> decltype(static_cast<Derived&&>(d)(static_cast<T&&>(t)))
{ return static_cast<Derived&&>(d)(static_cast<T&&>(t)); }

template<class T>
friend constexpr auto operator|(T&& t, const Derived&& d)
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68093
-> decltype(static_cast<const Derived&&>(d)(static_cast<T&&>(t)))
{ return static_cast<const Derived&&>(d)(static_cast<T&&>(t)); }
};

template<class _Ty>
META_CONCEPT _Stateless = Constructible<_Ty> && std::is_empty_v<_Ty>;

template<std::size_t, class T>
struct __box {
STL2_NO_UNIQUE_ADDRESS T value_;
};

template<class Indices, class Fn, class... Ts>
struct __closure;

template<std::size_t... Is, class Fn, class... Ts>
requires _Stateless<Fn> && (CopyConstructible<Ts> && ...)
struct STL2_EMPTY_BASES __closure<std::index_sequence<Is...>, Fn, Ts...>
: private __box<Is, Ts>... {
__closure() = default;
constexpr explicit __closure(Fn, Ts&&... ts)
: __box<Is, Ts>{static_cast<Ts&&>(ts)}... {}

template<class T>
requires Invocable<Fn, T, Ts &...>
constexpr auto operator()(T&& t) & {
return Fn{}(static_cast<T&&>(t),
static_cast<__box<Is, Ts>&>(*this).value_...);
}
template<class T>
requires Invocable<Fn, T, const Ts &...>
constexpr auto operator()(T&& t) const & {
return Fn{}(static_cast<T&&>(t),
static_cast<const __box<Is, Ts>&>(*this).value_...);
}
template<class T>
requires Invocable<Fn, T, Ts...>
constexpr auto operator()(T&& t) && {
return Fn{}(static_cast<T&&>(t),
static_cast<__box<Is, Ts>&&>(*this).value_...);
}
template<class T>
requires Invocable<Fn, T, const Ts...>
constexpr auto operator()(T&& t) const && {
return Fn{}(static_cast<T&&>(t),
static_cast<const __box<Is, Ts>&&>(*this).value_...);
}
};

template<_Stateless Fn, CopyConstructible... Ts>
struct STL2_EMPTY_BASES closure
: __pipeable<closure<Fn, Ts...>>
, __closure<std::index_sequence_for<Ts...>, Fn, Ts...> {
using __closure<std::index_sequence_for<Ts...>, Fn, Ts...>::__closure;
};

template<class Fn, class... Ts>
closure(Fn, Ts&&...) -> closure<Fn, Ts...>;

template<Pipeable Left, Pipeable Right>
struct __pipeline : __pipeable<__pipeline<Left, Right>> {
__pipeline() = default;
constexpr __pipeline(Left&& left, Right&& right)
: left_(std::move(left)), right_(std::move(right)) {}

template<class T>
requires Invocable<Left&, T> && Invocable<Right&, invoke_result_t<Left&, T>>
constexpr decltype(auto) operator()(T&& t) &
{ return right_(left_(static_cast<T&&>(t))); }

template<class T>
requires Invocable<const Left&, T> &&
Invocable<const Right&, invoke_result_t<const Left&, T>>
constexpr decltype(auto) operator()(T&& t) const &
{ return right_(left_(static_cast<T&&>(t))); }

template<class T>
requires Invocable<Left, T> && Invocable<Right, invoke_result_t<Left, T>>
constexpr decltype(auto) operator()(T&& t) &&
{ return static_cast<Right&&>(right_)(static_cast<Left&&>(left_)(static_cast<T&&>(t))); }
private:
STL2_NO_UNIQUE_ADDRESS Left left_;
STL2_NO_UNIQUE_ADDRESS Right right_;
};
}
} STL2_CLOSE_NAMESPACE

#endif
6 changes: 2 additions & 4 deletions include/stl2/detail/compressed_pair.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,10 @@ STL2_OPEN_NAMESPACE {
using second_t = detail::ebo_box<U, meta::size_t<1>>;
public:
compressed_pair()
requires DefaultConstructible<T> &&
DefaultConstructible<U> = default;
requires DefaultConstructible<T> && DefaultConstructible<U> = default;

template<typename TT = T, typename UU = U>
requires
Constructible<T, TT> && Constructible<U, UU>
requires Constructible<T, TT> && Constructible<U, UU>
constexpr compressed_pair(TT&& t, UU&& u)
noexcept(is_nothrow_constructible<first_t, TT&&>::value &&
is_nothrow_constructible<second_t, UU&&>::value)
Expand Down
85 changes: 54 additions & 31 deletions include/stl2/detail/concepts/compare.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,38 @@ STL2_OPEN_NAMESPACE {
META_CONCEPT Boolean =
Movable<std::decay_t<B>> &&
requires(const std::remove_reference_t<B>& b1,
const std::remove_reference_t<B>& b2, const bool a) {
// Requirements common to both Boolean and BooleanTestable.
{ b1 } -> STL2_RVALUE_REQ(ConvertibleTo<bool>);
{ !b1 } -> STL2_RVALUE_REQ(ConvertibleTo<bool>);
{ b1 && a } -> STL2_RVALUE_REQ(Same<bool>);
{ b1 || a } -> STL2_RVALUE_REQ(Same<bool>);

// Requirements of Boolean that are also be valid for
// BooleanTestable, but for which BooleanTestable does not
// require validation.
{ b1 && b2 } -> STL2_RVALUE_REQ(Same<bool>);
{ a && b2 } -> STL2_RVALUE_REQ(Same<bool>);
{ b1 || b2 } -> STL2_RVALUE_REQ(Same<bool>);
{ a || b2 } -> STL2_RVALUE_REQ(Same<bool>);

// Requirements of Boolean that are not required by
// BooleanTestable.
{ b1 == b2 } -> STL2_RVALUE_REQ(ConvertibleTo<bool>);
{ b1 == a } -> STL2_RVALUE_REQ(ConvertibleTo<bool>);
{ a == b2 } -> STL2_RVALUE_REQ(ConvertibleTo<bool>);
{ b1 != b2 } -> STL2_RVALUE_REQ(ConvertibleTo<bool>);
{ b1 != a } -> STL2_RVALUE_REQ(ConvertibleTo<bool>);
{ a != b2 } -> STL2_RVALUE_REQ(ConvertibleTo<bool>);
const std::remove_reference_t<B>& b2, const bool a) {
#if STL2_BROKEN_COMPOUND_REQUIREMENT
b1; requires ConvertibleTo<decltype((b1)), bool>;
!b1; requires ConvertibleTo<decltype(!b1), bool>;
b1 && b2; requires Same<decltype(b1 && b2), bool>;
b1 && a; requires Same<decltype(b1 && a), bool>;
a && b2; requires Same<decltype( a && b2), bool>;
b1 || b2; requires Same<decltype(b1 || b2), bool>;
b1 || a; requires Same<decltype(b1 || a), bool>;
a || b2; requires Same<decltype( a || b2), bool>;
b1 == b2; requires ConvertibleTo<decltype(b1 == b2), bool>;
b1 == a; requires ConvertibleTo<decltype(b1 == a ), bool>;
a == b2; requires ConvertibleTo<decltype( a == b2), bool>;
b1 != b2; requires ConvertibleTo<decltype(b1 != b2), bool>;
b1 != a; requires ConvertibleTo<decltype(b1 != a ), bool>;
a != b2; requires ConvertibleTo<decltype( a != b2), bool>;
#else
{ b1 } -> ConvertibleTo<bool>;
{ !b1 } -> ConvertibleTo<bool>;
{ b1 && b2 } -> Same<bool>;
{ b1 && a } -> Same<bool>;
{ a && b2 } -> Same<bool>;
{ b1 || b2 } -> Same<bool>;
{ b1 || a } -> Same<bool>;
{ a || b2 } -> Same<bool>;
{ b1 == b2 } -> ConvertibleTo<bool>;
{ b1 == a } -> ConvertibleTo<bool>;
{ a == b2 } -> ConvertibleTo<bool>;
{ b1 != b2 } -> ConvertibleTo<bool>;
{ b1 != a } -> ConvertibleTo<bool>;
{ a != b2 } -> ConvertibleTo<bool>;
#endif // STL2_BROKEN_COMPOUND_REQUIREMENT
};

///////////////////////////////////////////////////////////////////////////
Expand All @@ -66,10 +75,17 @@ STL2_OPEN_NAMESPACE {
META_CONCEPT WeaklyEqualityComparable =
requires(const std::remove_reference_t<T>& t,
const std::remove_reference_t<U>& u) {
{ t == u } -> STL2_RVALUE_REQ(Boolean);
{ t != u } -> STL2_RVALUE_REQ(Boolean);
{ u == t } -> STL2_RVALUE_REQ(Boolean);
{ u != t } -> STL2_RVALUE_REQ(Boolean);
#if STL2_BROKEN_COMPOUND_REQUIREMENT
t == u; requires Boolean<decltype(t == u)>;
t != u; requires Boolean<decltype(t != u)>;
u == t; requires Boolean<decltype(u == t)>;
u != t; requires Boolean<decltype(u != t)>;
#else
{ t == u } -> Boolean;
{ t != u } -> Boolean;
{ u == t } -> Boolean;
{ u != t } -> Boolean;
#endif // STL2_BROKEN_COMPOUND_REQUIREMENT
};

///////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -99,10 +115,17 @@ STL2_OPEN_NAMESPACE {
META_CONCEPT __totally_ordered =
requires(const std::remove_reference_t<T>& t,
const std::remove_reference_t<U>& u) {
{ t < u } -> STL2_RVALUE_REQ(Boolean);
{ t > u } -> STL2_RVALUE_REQ(Boolean);
{ t <= u } -> STL2_RVALUE_REQ(Boolean);
{ t >= u } -> STL2_RVALUE_REQ(Boolean);
#if STL2_BROKEN_COMPOUND_REQUIREMENT
t < u; requires Boolean<decltype(t < u)>;
t > u; requires Boolean<decltype(t > u)>;
t <= u; requires Boolean<decltype(t <= u)>;
t >= u; requires Boolean<decltype(t >= u)>;
#else
{ t < u } -> Boolean;
{ t > u } -> Boolean;
{ t <= u } -> Boolean;
{ t >= u } -> Boolean;
#endif // STL2_BROKEN_COMPOUND_REQUIREMENT
// Axiom: t < u, t > u, t <= u, t >= u have the same definition space.
// Axiom: If bool(t < u) then bool(t <= u)
// Axiom: If bool(t > u) then bool(t >= u)
Expand Down
Loading