Skip to content

library: C++23 — deducing this for some recursive lambdas#229

Merged
cameroncuster merged 7 commits into
devfrom
cpp23-library
Jul 7, 2026
Merged

library: C++23 — deducing this for some recursive lambdas#229
cameroncuster merged 7 commits into
devfrom
cpp23-library

Conversation

@cameroncuster

@cameroncuster cameroncuster commented Jul 7, 2026

Copy link
Copy Markdown
Member

Converts the library to C++23. Companion to #228 (infra/tests std bump), which this PR is stacked on — it must merge after #228, since the code here needs -std=c++23 to compile.

Deducing this for recursive lambdas (15 lambdas, 12 files)

Recursive lambdas in library/ converted from the pass-self-explicitly idiom:

// before
auto dfs = [&](auto&& dfs, int u) -> void { ... dfs(dfs, v) ... };
dfs(dfs, 0);
// after
auto dfs = [&](this auto&& dfs, int u) -> void { ... dfs(v) ... };
dfs(0);

Justification (correct/efficient/readable):

  • Readable: removes the self-parameter and the doubled first argument at every recursion and call site — the most confusing idiom in the codebase for newcomers, and strictly shorter.
  • Correct: no way to accidentally pass the wrong callable as the self argument.
  • Efficient: no change; same calls after inlining.

Converted files: trees/{centroid_decomp ×2, edge_cd ×2, shallowest_decomp_tree, uncommon/subtree_isomorphism}, graphs/{bcc_callback, euler_path, scc, uncommon/{bridges, cuts}, strongly_connected_components/{offline_incremental_scc, add_edges_strongly_connected}}, convolution/min_plus_convolution_convex_and_arbitrary.

Not converted (GCC bug): the 8 lambdas inside struct constructors — trees/{hld ×2, tree_lift, lca_rmq, linear_lca, uncommon/{hagerup_kth_par, ladder_decomposition, linear_kth_par}} — access data members through the captured this. GCC 14/15 rejects member access inside a deducing-this lambda that captures the enclosing this (GCC PR113563, fixed in GCC 16). CI's g++-14 (same as the Kattis judge) fails on them, so they keep the pass-self idiom until the toolchain moves past the bug.

library/contest/tester.sh: -std=c++20-std=c++23

The stress tester should compile with the same standard as the contest judge (SEUSA 2025 on Kattis: g++-14 -std=gnu++23).

Evaluated and rejected: std::generator for get_prime_factors.hpp

Measured before deciding. Rewriting the factor loop as a std::generator<int> coroutine:

  • 2.7× slower — factorizing all of [2, 1e7): loop idiom 160 ms vs generator 430 ms (g++ -O2), plus a heap allocation per call (coroutine frame)
  • Trips -Werror — GCC's own <generator> triggers -Wmismatched-new-delete under -O2 -Wall (known false positive, GCC PR109224, still open), which would fail compile_gcc CI and require a suppression for zero gain

The existing "loop header you complete with a body" idiom stays.

Validation

  • CI compile_gcc (g++-14) confirmed the constructor-lambda failures; those 7 files reverted, everything else passes
  • All test files covering the changed headers compile clean with g++ -std=c++23 -O2 -Wall -Wextra
  • clang-format --dry-run --Werror passes on all changed files
  • Grep sweep: zero remaining NAME(NAME, ...) self-passing call sites in the converted files
  • Behavior is identical (pure syntax transformation); the full verifier run in CI on top of tests/infra: move to C++23 (std pins, g++-14 in CI, deducing this in test code) #228's toolchain is the final gate

@cameroncuster cameroncuster changed the title library: C++23 — deducing this for all recursive lambdas library: C++23 — deducing this for some recursive lambdas Jul 7, 2026
Base automatically changed from cpp23-tests to dev July 7, 2026 16:17
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