Skip to content

standardize on c++20: ranges/views and <bit> used consistently#221

Merged
cameroncuster merged 14 commits into
devfrom
cpp20
Jul 6, 2026
Merged

standardize on c++20: ranges/views and <bit> used consistently#221
cameroncuster merged 14 commits into
devfrom
cpp20

Conversation

@cameroncuster

@cameroncuster cameroncuster commented Jul 6, 2026

Copy link
Copy Markdown
Member

Standardize on C++20 across the library: use ranges::/views:: and <bit> consistently wherever they apply, so there's one predictable way each idiom is written. Consistency is the goal — a conversion is only skipped when the C++20 form doesn't exist, doesn't compile, or is measurably worse.

Changes

ranges algorithms (full-range)

  • graphs/mst.hpp: two-argument comparator lambda -> ranges::sort projection
  • strings/wildcard_pattern_matching.hpp: reverse(all(t_pw)) -> ranges::reverse(t_pw)
  • strings/suffix_array/find/find_string_bs_fast.hpp: lower_bound(all(sa), 0, cmp) -> ranges::lower_bound(sa, 0, cmp)
  • data_structures_[l,r)/uncommon/priority_queue_of_updates.hpp: reverse_copy(all(extra), it) -> ranges::reverse_copy(extra, it)
  • data_structures_[l,r)/uncommon/deque_op.hpp: two transform(all(x), out, f) -> ranges::transform(x, out, f)

views for offset ranges

Offset-all() and begin()+k idioms now use views::drop/views::take, matching the pre-existing views::drop in rmq.hpp:

  • math/matrix_related/solve_linear_mod.hpp: any_of(rank + all(mat), ...) -> mat | views::drop(rank); for_each(begin(mat), begin(mat) + rank, ...) -> mat | views::take(rank)
  • strings/suffix_array/find/find_substring.hpp: lower_bound(begin(sa) + k, ...) -> ranges::lower_bound(sa | views::drop(k), ...) / views::take
  • strings/suffix_array/find/find_string_bs_fast.hpp: offset lower_bound -> sa | views::drop(sa_le)

<bit> instead of __lg

All 12 __lg sites now use bit_width/bit_floor (the library already used countr_zero/bit_ceil elsewhere): both rmq.hpps, disjoint_rmq.hpp, seg_tree.hpp, seg_tree_midpoint.hpp, both max_right.hpp/min_left.hpp pairs, range_parallel_dsu.hpp, ladder_decomposition.hpp, linear_kth_par.hpp.

Doc examples

  • flow/hungarian.hpp: @code example (ll)0 C-style cast -> ll(0)
  • NULL stays: the repo's grep check intentionally enforces NULL over nullptr in the library

Not converted (with reasons)

  • unique/remove_if/partition (virtual_tree, edge_cd, offline_incremental_scc, priority_queue_of_updates): the ranges:: versions return a subrange, so every call site needs a begin(...) unwrap (and ranges::subrange(el, er) wrapping for iterator pairs) — longer, noisier, and cppcheck flags the erase idiom as a mismatchingContainerExpression false positive. Rule of thumb: use ranges:: when it consumes a range; keep the iterator form when you'd have to unwrap a returned subrange
  • find_substrings_concatenated.hpp lower_bound(begin(sa) + sa_le, begin(sa) + sa_ri, ...): the comparator is intentionally asymmetric (cmp(int, const dt&)); ranges::lower_bound requires indirect_strict_weak_order, i.e. cmp(dt&, dt&) must be invocable, so the ranges form does not compile
  • partial_sum, adjacent_difference, iota (algorithm): no ranges:: counterpart in C++20 (C++23's fold/views::enumerate territory)
  • seg-tree midpoints tl + (tr - tl) / 2 -> midpoint(tl, tr): GCC emits branchy codegen for std::midpoint vs 3 branchless instructions for the manual form — slower in hot recursion paths
  • contains/starts_with/ends_with/erase_if: no applicable call sites in the library (ranges::contains itself is C++23)

Related but split out: passing recursive-lambda self parameters as auto&& is PR #222.

Verification

  • all affected tests compile with g++ -std=c++20 -O2 -Wall -Wextra (61 tests touching the changed headers)
  • clang-format --dry-run --Werror passes with tests/.config/dev.clang-format on all touched headers
  • grep checks pass (no .begin()/.size() member-call forms, no __lg remaining)
  • auto-verifier runs on each commit

@cameroncuster cameroncuster changed the title use c++20 ranges where shorter lean into c++20: use ranges/views wherever it's a strict win Jul 6, 2026
Cameron Custer added 6 commits July 6, 2026 11:42
# Conflicts:
#	.verify-helper/timestamps.remote.json
#	library/data_structures_[l,r)/uncommon/priority_queue_of_updates.hpp
# Conflicts:
#	.verify-helper/timestamps.remote.json
@cameroncuster cameroncuster changed the title lean into c++20: use ranges/views wherever it's a strict win standardize on c++20: ranges/views and <bit> used consistently Jul 6, 2026
…o iterator form; drop cppcheck suppression
@cameroncuster cameroncuster merged commit e60f0b1 into dev Jul 6, 2026
7 of 8 checks passed
@cameroncuster cameroncuster deleted the cpp20 branch July 6, 2026 20:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants