Skip to content

Commit

Permalink
findIndirect(): factor out common constraint into a concept
Browse files Browse the repository at this point in the history
  • Loading branch information
KitsuneRal committed Nov 29, 2024
1 parent e9e2dcd commit fb51cc1
Showing 1 changed file with 13 additions and 13 deletions.
26 changes: 13 additions & 13 deletions Quotient/ranges_extras.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ namespace Quotient {

//! Same as std::projected but Proj is checked against the reference under the iterator
template <std::indirectly_readable IterT,
std::indirectly_regular_unary_invocable<std::iter_reference_t<IterT>> Proj>
using IndirectlyProjected = std::projected<std::iter_reference_t<IterT>, Proj>;
std::indirectly_regular_unary_invocable<std::iter_reference_t<IterT>> ProjT>
using IndirectlyProjected = std::projected<std::iter_reference_t<IterT>, ProjT>;

//! Same as std::indirectly_comparable but uses IndirectlyProjected<> instead of std::projected<>
template <typename IterT, typename ValT, typename ProjT, typename CompT = std::ranges::equal_to>
concept IndirectlyProjectedComparable =
std::indirect_binary_predicate<CompT, IndirectlyProjected<IterT, ProjT>, const ValT*>;

//! \brief Find a value in a container of (smart) pointers
//!
Expand All @@ -17,24 +22,19 @@ using IndirectlyProjected = std::projected<std::iter_reference_t<IterT>, 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 <std::input_iterator IterT, typename ValT, typename Proj = std::identity>
requires std::indirect_binary_predicate<std::ranges::equal_to,
IndirectlyProjected<IterT, Proj>, 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 <std::input_iterator IterT, typename ValT, typename ProjT = std::identity>
requires IndirectlyProjectedComparable<IterT, ValT, ProjT>
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);
});
}

//! The overload of findIndirect for ranges
template <typename RangeT, typename ValT, typename Proj = std::identity>
requires std::indirect_binary_predicate<
std::ranges::equal_to, IndirectlyProjected<std::ranges::iterator_t<RangeT>, Proj>,
const ValT*>
inline constexpr auto findIndirect(RangeT&& range, const ValT& value, Proj proj = {})
template <typename RangeT, typename ValT, typename ProjT = std::identity>
requires IndirectlyProjectedComparable<std::ranges::iterator_t<RangeT>, 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));
}
Expand Down

0 comments on commit fb51cc1

Please sign in to comment.