migrate to std::ranges

Move the various seq_ functions, as well as std::(stable_)sort,
std::accumulate, std::transform, std::find, std::find_if to their C++20
std::ranges counterparts.
This commit is contained in:
Dirk-Jan C. Binnema
2026-07-24 21:28:58 +03:00
committed by Seth Ladygo
parent 1b42ad6099
commit 4489d513be
29 changed files with 71 additions and 131 deletions

View File

@ -224,7 +224,7 @@ struct CommandHandler {
std::vector<std::string> names;
for (auto&& arg : args)
names.emplace_back(arg.first);
std::sort(names.begin(), names.end(), [&](const auto& name1, const auto& name2) {
std::ranges::sort(names, [&](const auto& name1, const auto& name2) {
const auto& arg1{args.find(name1)->second};
const auto& arg2{args.find(name2)->second};
if (arg1.required != arg2.required)

View File

@ -354,7 +354,7 @@ needs_separator(std::string_view tagname)
constexpr auto nosep_tags = std::to_array<const char*>({
"b", "em", "i", "s", "strike", "tt", "u"
});
return !seq_some(nosep_tags, [&](auto&& t){return matches(tagname, t);});
return !std::ranges::any_of(nosep_tags, [&](auto&& t){return matches(tagname, t);});
}
static bool // do we need to skip the element completely?
@ -363,7 +363,7 @@ is_skip_element(std::string_view tagname)
constexpr auto skip_tags = std::to_array<const char*>({
"head", "title"
});
return seq_some(skip_tags, [&](auto&& t){return matches(tagname, t);});
return std::ranges::any_of(skip_tags, [&](auto&& t){return matches(tagname, t);});
}
// skip the end-tag
@ -518,7 +518,7 @@ html_escape_char(Context& ctx)
if (matches(esc, n.name))
return std::string{n.repl};
if (seq_some(accents, [&](auto&& a){
if (std::ranges::any_of(accents, [&](auto&& a){
return starts_with(esc.substr(1), a);}))
return std::string(1, to_ascii_lower(esc.front()));

View File

@ -34,7 +34,6 @@
#include <string.h>
#include <iostream>
#include <algorithm>
#include <numeric>
#include <functional>
#include <cinttypes>
#include <charconv>
@ -339,25 +338,18 @@ Mu::join(const std::vector<std::string>& svec, const std::string& sepa)
/* calculate the overall size beforehand, to avoid re-allocations. */
size_t value_len =
std::accumulate(svec.cbegin(), svec.cend(), std::size_t{},
[](size_t size, const std::string& s) {
return size + s.size();
}) + (svec.size() - 1) * sepa.length();
size_t value_len{(svec.size() - 1) * sepa.length()};
for (const auto& s : svec)
value_len += s.size();
std::string value;
value.reserve(value_len);
std::accumulate(svec.cbegin(), svec.cend(), std::ref(value),
[&](std::string& s1, const std::string& s2)->std::string& {
if (s1.empty())
s1 = s2;
else {
s1.append(sepa);
s1.append(s2);
}
return s1;
});
value.append(svec.front());
for (auto it = std::next(svec.cbegin()); it != svec.cend(); ++it) {
value.append(sepa);
value.append(*it);
}
return value;
}

View File

@ -656,56 +656,6 @@ inline std::string shell_quote(const std::string& str) {
std::string to_lexnum(int64_t val);
int64_t from_lexnum(const std::string& str);
/**
* Like std::find_if, but using sequence instead of a range.
*
* @param seq some std::find_if compatible sequence
* @param pred a predicate
*
* @return an iterator
*/
template<typename Sequence, typename UnaryPredicate>
typename Sequence::const_iterator seq_find_if(const Sequence& seq, UnaryPredicate pred) {
return std::find_if(seq.cbegin(), seq.cend(), pred);
}
/**
* Is pred(element) true for at least one element of sequence?
*
* @param seq sequence
* @param pred a predicate
*
* @return true or false
*/
template<typename Sequence, typename UnaryPredicate>
bool seq_some(const Sequence& seq, UnaryPredicate pred) {
return seq_find_if(seq, pred) != seq.cend();
}
/**
* Create a sequence that has all element of seq for which pred is false
*
* @param seq sequence
* @param pred false
*
* @return sequence
*/
template<typename Sequence, typename UnaryPredicate>
Sequence seq_remove(const Sequence& seq, UnaryPredicate pred) {
Sequence res;
std::remove_copy_if(seq.begin(), seq.end(), std::back_inserter(res), pred);
return res;
}
template<typename Sequence, typename Compare>
void seq_sort(Sequence& seq, Compare cmp) { std::sort(seq.begin(), seq.end(), cmp); }
template<typename Sequence, typename UnaryOp>
void seq_for_each(const Sequence& seq, UnaryOp op) {
std::for_each(seq.cbegin(), seq.cend(), op);
}
struct MaybeAnsi {
explicit MaybeAnsi(bool use_color) : color_{use_color} {}

View File

@ -260,6 +260,10 @@ test_join()
assert_equal(join({"a", "b", "c"}, ""), "abc");
assert_equal(join({},"foo"), "");
assert_equal(join({"d", "e", "f"}, "foo"), "dfooefoof");
// empty elements are joined, too
assert_equal(join({"", "a"}, ","), ",a");
assert_equal(join({"", ""}, ","), ",");
assert_equal(join({"a"}, ","), "a");
}