diff --git a/Quotient/ranges_extras.h b/Quotient/ranges_extras.h index 38ee933a1..9555409ba 100644 --- a/Quotient/ranges_extras.h +++ b/Quotient/ranges_extras.h @@ -6,8 +6,13 @@ namespace Quotient { //! Same as std::projected but Proj is checked against the reference under the iterator template > Proj> -using IndirectlyProjected = std::projected, Proj>; + std::indirectly_regular_unary_invocable> ProjT> +using IndirectlyProjected = std::projected, ProjT>; + +//! Same as std::indirectly_comparable but uses IndirectlyProjected<> instead of std::projected<> +template +concept IndirectlyProjectedComparable = + std::indirect_binary_predicate, const ValT*>; //! \brief Find a value in a container of (smart) pointers //! @@ -17,12 +22,9 @@ using IndirectlyProjected = std::projected, Proj>; //! searching for events that match a specific simple criterion; e.g., to find an event with a given //! id in a container you can now write `findIndirect(events, eventId, &RoomEvent::id);` instead //! of having to supply your own lambda to dereference the timeline item and check the event id. -template - requires std::indirect_binary_predicate, const ValT*> -// Most of constraints here (including IndirectlyProjected) are based on the definition of -// std::ranges::find and things around it -inline constexpr auto findIndirect(IterT from, IterT to, const ValT& value, Proj proj = {}) +template + requires IndirectlyProjectedComparable +inline constexpr auto findIndirect(IterT from, IterT to, const ValT& value, ProjT proj = {}) { return std::ranges::find(from, to, value, [p = std::move(proj)](auto& itemPtr) { return std::invoke(p, *itemPtr); @@ -30,11 +32,9 @@ inline constexpr auto findIndirect(IterT from, IterT to, const ValT& value, Proj } //! The overload of findIndirect for ranges -template - requires std::indirect_binary_predicate< - std::ranges::equal_to, IndirectlyProjected, Proj>, - const ValT*> -inline constexpr auto findIndirect(RangeT&& range, const ValT& value, Proj proj = {}) +template + requires IndirectlyProjectedComparable, ValT, ProjT> +inline constexpr auto findIndirect(RangeT&& range, const ValT& value, ProjT proj = {}) { return findIndirect(std::ranges::begin(range), std::ranges::end(range), value, std::move(proj)); }