standardize on c++20: ranges/views and <bit> used consistently#221
Merged
Conversation
added 3 commits
July 6, 2026 11:17
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
…anges::unique)" This reverts commit 80a247a.
…p/take, __lg -> bit_width/bit_floor
# Conflicts: # .verify-helper/timestamps.remote.json
…nges::unique in virtual_tree
…o iterator form; drop cppcheck suppression
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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::sortprojectionstrings/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: twotransform(all(x), out, f)->ranges::transform(x, out, f)views for offset ranges
Offset-
all()andbegin()+kidioms now useviews::drop/views::take, matching the pre-existingviews::dropinrmq.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::takestrings/suffix_array/find/find_string_bs_fast.hpp: offsetlower_bound->sa | views::drop(sa_le)<bit>instead of__lgAll 12
__lgsites now usebit_width/bit_floor(the library already usedcountr_zero/bit_ceilelsewhere): bothrmq.hpps,disjoint_rmq.hpp,seg_tree.hpp,seg_tree_midpoint.hpp, bothmax_right.hpp/min_left.hpppairs,range_parallel_dsu.hpp,ladder_decomposition.hpp,linear_kth_par.hpp.Doc examples
flow/hungarian.hpp:@codeexample(ll)0C-style cast ->ll(0)NULLstays: the repo's grep check intentionally enforcesNULLovernullptrin the libraryNot converted (with reasons)
unique/remove_if/partition(virtual_tree, edge_cd, offline_incremental_scc, priority_queue_of_updates): theranges::versions return a subrange, so every call site needs abegin(...)unwrap (andranges::subrange(el, er)wrapping for iterator pairs) — longer, noisier, and cppcheck flags the erase idiom as amismatchingContainerExpressionfalse positive. Rule of thumb: useranges::when it consumes a range; keep the iterator form when you'd have to unwrap a returned subrangefind_substrings_concatenated.hpplower_bound(begin(sa) + sa_le, begin(sa) + sa_ri, ...): the comparator is intentionally asymmetric (cmp(int, const dt&));ranges::lower_boundrequiresindirect_strict_weak_order, i.e.cmp(dt&, dt&)must be invocable, so the ranges form does not compilepartial_sum,adjacent_difference,iota(algorithm): noranges::counterpart in C++20 (C++23'sfold/views::enumerateterritory)tl + (tr - tl) / 2->midpoint(tl, tr): GCC emits branchy codegen forstd::midpointvs 3 branchless instructions for the manual form — slower in hot recursion pathscontains/starts_with/ends_with/erase_if: no applicable call sites in the library (ranges::containsitself is C++23)Related but split out: passing recursive-lambda self parameters as
auto&&is PR #222.Verification
g++ -std=c++20 -O2 -Wall -Wextra(61 tests touching the changed headers)clang-format --dry-run --Werrorpasses withtests/.config/dev.clang-formaton all touched headers.begin()/.size()member-call forms, no__lgremaining)