Skip to content

Commit

Permalink
Drop findIndirect() algorithm
Browse files Browse the repository at this point in the history
According to cppreference.com, std::invoke is supposed to deal with one
level of indirection automatically (e.g. if the first parameter is a
smart pointer), so we should not need findIndirect() for that. What
findIndirect() effectively does is enabling the second level of
indirection, and that kind of stuff better be spelled out in the code
instead of being magically consumed by an algorithm.
  • Loading branch information
KitsuneRal committed Dec 3, 2024
1 parent 75d559d commit f3615df
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Quotient/events/event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ using namespace Quotient;
void AbstractEventMetaType::addDerived(const AbstractEventMetaType* newType)
{
if (const auto existing =
findIndirect(_derivedTypes, newType->matrixId, &AbstractEventMetaType::matrixId);
std::ranges::find(_derivedTypes, newType->matrixId, &AbstractEventMetaType::matrixId);
existing != _derivedTypes.cend()) {
if (*existing == newType)
return;
Expand Down
35 changes: 0 additions & 35 deletions Quotient/ranges_extras.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,6 @@

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>> 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
//!
//! This is a replica of std::ranges::find that automatically applies dereferencing projection
//! before applying the provided projection. Quotient has a few containers with pointers or wrappers
//! for other types - think of timeline items or `event_ptr_tt<>`s. This is meant to streamline
//! 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 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 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));
}

//! \brief An indexOf() alternative for any range
//!
//! Unlike QList::indexOf(), returns `range.size()` if \p value is not found
Expand Down
14 changes: 7 additions & 7 deletions Quotient/room.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1102,12 +1102,12 @@ Room::rev_iter_t Room::findInTimeline(const QString& evtId) const

Room::PendingEvents::iterator Room::findPendingEvent(const QString& txnId)
{
return findIndirect(d->unsyncedEvents, txnId, &RoomEvent::transactionId);
return std::ranges::find(d->unsyncedEvents, txnId, &RoomEvent::transactionId);
}

Room::PendingEvents::const_iterator Room::findPendingEvent(const QString& txnId) const
{
return findIndirect(d->unsyncedEvents, txnId, &RoomEvent::transactionId);
return std::ranges::find(d->unsyncedEvents, txnId, &RoomEvent::transactionId);
}

const Room::RelatedEvents Room::relatedEvents(
Expand Down Expand Up @@ -2815,18 +2815,19 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events)
et.start();

{
using namespace std::ranges;
// Pre-process redactions and edits so that events that get
// redacted/replaced in the same batch landed in the timeline already
// treated.
// NB: We have to store redacting/replacing events to the timeline too -
// see #220.
auto it = std::ranges::find_if(events, isEditing);
for (const auto& eptr : std::ranges::subrange(it, events.end())) {
auto it = find_if(events, isEditing);
for (const auto& eptr : subrange(it, events.end())) {
if (auto* r = eventCast<RedactionEvent>(eptr)) {
// Try to find the target in the timeline, then in the batch.
if (processRedaction(*r))
continue;
if (auto targetIt = findIndirect(events, r->redactedEvent(), &RoomEvent::id);
if (auto targetIt = find(events, r->redactedEvent(), &RoomEvent::id);
targetIt != events.end())
*targetIt = makeRedacted(**targetIt, *r);
else
Expand All @@ -2839,8 +2840,7 @@ Room::Changes Room::Private::addNewMessageEvents(RoomEvents&& events)
msg && !msg->replacedEvent().isEmpty()) {
if (processReplacement(*msg))
continue;
if (auto targetIt =
findIndirect(events.begin(), it, msg->replacedEvent(), &RoomEvent::id);
if (auto targetIt = find(events.begin(), it, msg->replacedEvent(), &RoomEvent::id);
targetIt != it)
*targetIt = makeReplaced(**targetIt, *msg);
else // FIXME: hide the replacing event when target arrives later
Expand Down

0 comments on commit f3615df

Please sign in to comment.