diff --git a/Quotient/connection.cpp b/Quotient/connection.cpp index 3c19e1598..53dd1ee7f 100644 --- a/Quotient/connection.cpp +++ b/Quotient/connection.cpp @@ -12,6 +12,7 @@ #include "database.h" #include "logging_categories_p.h" #include "qt_connection_util.h" +#include "ranges_extras.h" #include "room.h" #include "settings.h" #include "user.h" @@ -1665,13 +1666,12 @@ QVector Connection::availableRoomVersions() co // Can't stuff QKeyValueRange in a std:: view directly because it's not move-assignable and // most views require that - using std::views::all to go around this - // TODO: use std::ranges::to() when all toolchains support it const auto allVersions = d->capabilities.roomVersions->available.asKeyValueRange(); - auto allVersionsView = std::views::all(allVersions) | std::views::transform([](const auto& p) { - return SupportedRoomVersion{ p.first, p.second }; - }); - QVector result(allVersionsView.begin(), allVersionsView.end()); - // Put stable versions over unstable; for + auto result = + rangeTo(std::views::all(allVersions) | std::views::transform([](const auto& p) { + return SupportedRoomVersion{ p.first, p.second }; + })); + // Put stable versions over unstable std::ranges::sort(result, [](const SupportedRoomVersion& v1, const SupportedRoomVersion& v2) { if (const auto stable1 = v1.isStable(), stable2 = v2.isStable(); stable1 != stable2) return stable1 && !stable2; // Put all stable versions over unstable diff --git a/Quotient/ranges_extras.h b/Quotient/ranges_extras.h index d19a376eb..5cd0df2e7 100644 --- a/Quotient/ranges_extras.h +++ b/Quotient/ranges_extras.h @@ -16,4 +16,36 @@ inline auto findIndex(const RangeT& range, const ValT& value, ProjT proj = {}) return distance(begin(range), find(range, value, std::move(proj))); } +//! \brief A replacement of std::ranges::to() while toolchains catch up +//! +//! Returns a container of type \p TargetT created from \p sourceRange. Unlike std::ranges::to(), +//! you have to pass the range to it (e.g. `rangeTo(someRange)`); using it in a pipeline +//! (`someRange | rangeTo()`) won't compile. Internally calls std::ranges::to() if it's +//! available; otherwise, returns the result of calling +//! `TargetT(ranges::begin(sourceRange), ranges::end(sourceRange))`. +template +[[nodiscard]] constexpr auto rangeTo(SourceT&& sourceRange) +{ +#if defined(__cpp_lib_ranges_to_container) + return std::ranges::to(std::forward(sourceRange)); +#else + using std::begin, std::end; + return TargetT(begin(sourceRange), end(sourceRange)); +#endif +} + +//! An overload that accepts unspecialised container template +template