Skip to content

Commit cc0212b

Browse files
convert single-call recursive lambdas to unnamed IIFEs (#245)
* convert single-call recursive lambdas to unnamed IIFEs For the 7 library files where a `this auto&&` recursive lambda is defined and invoked exactly once, drop the name and immediately invoke the lambda in place. This removes a redundant binding without changing behavior. Note: explicit return types are retained where present, since C++ cannot deduce the return type of a recursive lambda whose recursive call precedes any return. Verified: repo clang-format passes; all affected tests compile under both g++ and clang; self-contained handmade stress tests pass at runtime. * rename IIFE recursion parameter to `self` Per convention, name the `this auto&&` recursion parameter of the unnamed IIFEs `self` (previously `dfs`/`dnc`). Updates the parameter and all recursive call sites within each of the 7 IIFEs. No behavior change. * [auto-verifier] verify commit 0cae55d * suppress cppcheck containerOutOfBounds in edge_cd.hpp --------- Co-authored-by: GitHub <noreply@github.com>
1 parent 91773e8 commit cc0212b

8 files changed

Lines changed: 29 additions & 35 deletions

File tree

library/convolution/min_plus_convolution_convex_and_arbitrary.hpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ vi min_plus(const vi& convex, const vi& arbitrary) {
99
int n = sz(convex);
1010
int m = sz(arbitrary);
1111
vi res(n + m - 1, INT_MAX);
12-
auto dnc = [&](this auto&& dnc, int res_le, int res_ri,
13-
int arb_le, int arb_ri) {
12+
[&](this auto&& self, int res_le, int res_ri, int arb_le,
13+
int arb_ri) {
1414
if (res_le >= res_ri) return;
1515
int mid_res = (res_le + res_ri) / 2;
1616
int op_arb = arb_le;
@@ -22,10 +22,9 @@ vi min_plus(const vi& convex, const vi& arbitrary) {
2222
op_arb = i;
2323
}
2424
}
25-
dnc(res_le, mid_res, arb_le, min(arb_ri, op_arb + 1));
25+
self(res_le, mid_res, arb_le, min(arb_ri, op_arb + 1));
2626
// NOLINTNEXTLINE(readability-suspicious-call-argument)
27-
dnc(mid_res + 1, res_ri, op_arb, arb_ri);
28-
};
29-
dnc(0, n + m - 1, 0, m);
27+
self(mid_res + 1, res_ri, op_arb, arb_ri);
28+
}(0, n + m - 1, 0, m);
3029
return res;
3130
}

library/graphs/euler_path.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@
1717
vector<pii> euler_path(auto& g, int m, int s) {
1818
vi vis(m);
1919
vector<pii> path;
20-
auto dfs = [&](this auto&& dfs, int u, int eu) -> void {
20+
[&](this auto&& self, int u, int eu) -> void {
2121
while (!empty(g[u])) {
2222
auto [v, ev] = g[u].back();
2323
g[u].pop_back();
24-
if (!vis[ev]) vis[ev] = 1, dfs(v, ev);
24+
if (!vis[ev]) vis[ev] = 1, self(v, ev);
2525
}
2626
path.emplace_back(u, eu);
27-
};
28-
dfs(s, -1);
27+
}(s, -1);
2928
ranges::reverse(path);
3029
return path;
3130
}

library/graphs/strongly_connected_components/offline_incremental_scc.hpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ vi offline_incremental_scc(vector<array<int, 2>> eds,
1616
vi ids(n, -1), joins(m, m), idx(m), vs(n), scc_id;
1717
ranges::iota(idx, 0);
1818
vector<vi> g;
19-
auto dnc = [&](this auto&& dnc, auto el, auto er, int tl,
20-
int tr) {
19+
// uses -1 as the lower bound to correctly handle
20+
// self-edges
21+
[&](this auto&& self, auto el, auto er, int tl, int tr) {
2122
g.clear();
2223
int mid = midpoint(tl, tr);
2324
for (auto it = el; it != er; it++) {
@@ -42,11 +43,8 @@ vi offline_incremental_scc(vector<array<int, 2>> eds,
4243
auto& [u, v] = eds[*it];
4344
u = scc_id[u], v = scc_id[v];
4445
}
45-
dnc(el, split, tl, mid);
46-
dnc(split, er, mid, tr);
47-
};
48-
// uses -1 as the lower bound to correctly handle
49-
// self-edges
50-
dnc(all(idx), -1, m);
46+
self(el, split, tl, mid);
47+
self(split, er, mid, tr);
48+
}(all(idx), -1, m);
5149
return joins;
5250
}

library/trees/centroid_decomp.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ vi cd(auto& g, auto f) {
1919
}
2020
return 2 * s[u] >= n ? s[p] = n - s[u], u : -1;
2121
};
22-
auto dfs = [&](this auto&& dfs, int u) -> int {
22+
[&](this auto&& self, int u) -> int {
2323
f(u = ctd(u, u, s[u]));
24-
for (int v : g[u]) erase(g[v], u), p[dfs(v)] = u;
24+
for (int v : g[u]) erase(g[v], u), p[self(v)] = u;
2525
return u;
26-
};
27-
return dfs(0), p;
26+
}(0);
27+
return p;
2828
}

library/trees/edge_cd.hpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ template<class G> void edge_cd(vector<G>& g, auto f) {
2626
}
2727
return 2 * s[u] > m ? s[p] = m + 1 - s[u], u : -1;
2828
};
29-
auto dfs = [&](this auto&& dfs, int u, int m) {
29+
[&](this auto&& self, int u, int m) {
3030
if (m < 2) return;
3131
u = ctd(u, u, m);
3232
int sum = 0;
@@ -37,9 +37,8 @@ template<class G> void edge_cd(vector<G>& g, auto f) {
3737
f(u, it - begin(g[u]));
3838
G oth(it, end(g[u]));
3939
g[u].erase(it, end(g[u]));
40-
dfs(u, sum);
40+
self(u, sum);
4141
swap(g[u], oth);
42-
dfs(u, m - sum);
43-
};
44-
dfs(0, sz(g) - 1);
42+
self(u, m - sum);
43+
}(0, sz(g) - 1);
4544
};

library/trees/shallowest_decomp_tree.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,17 @@
99
//! @space O(n)
1010
void shallowest(auto& g, auto f) {
1111
vector<vi> order(bit_width(size(g)));
12-
auto dfs = [&](this auto&& dfs, int u, int p) -> int {
12+
[&](this auto&& self, int u, int p) -> int {
1313
int once = 0, twice = 0;
1414
for (int v : g[u])
1515
if (v != p) {
16-
int dp = dfs(v, u);
16+
int dp = self(v, u);
1717
twice |= once & dp, once |= dp;
1818
}
1919
auto dp = (once | (bit_ceil(twice + 1u) - 1)) + 1;
2020
order[countr_zero(dp)].push_back(u);
2121
return dp;
22-
};
23-
dfs(0, 0);
22+
}(0, 0);
2423
for (const vi& vec : order | views::reverse)
2524
for (int u : vec) {
2625
f(u);

library/trees/uncommon/subtree_isomorphism.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@
1212
auto subtree_iso(const auto& g) {
1313
vi iso_id(sz(g), -1);
1414
map<vi, int> hashes;
15-
auto dfs = [&](this auto&& dfs, int u, int p) -> int {
15+
[&](this auto&& self, int u, int p) -> int {
1616
vi ch_ids;
1717
for (int v : g[u])
18-
if (v != p) ch_ids.push_back(dfs(v, u));
18+
if (v != p) ch_ids.push_back(self(v, u));
1919
ranges::sort(ch_ids);
2020
return iso_id[u] =
2121
hashes.try_emplace(ch_ids, sz(hashes))
2222
.first->second;
23-
};
24-
dfs(0, 0);
23+
}(0, 0);
2524
return pair{sz(hashes), iso_id};
2625
}

tests/.config/.cppcheck_suppression_list

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ unusedFunction:../kactl/content/data-structures/UnionFind.h:14
6060
unusedFunction:../kactl/content/number-theory/ModPow.h:13
6161
unusedFunction:../kactl/stress-tests/utilities/genTree.h:49
6262
containerOutOfBounds:../library/data_structures_[l,r)/uncommon/permutation_tree.hpp:85
63+
containerOutOfBounds:../library/trees/edge_cd.hpp
6364
ctuOneDefinitionRuleViolation:../library/data_structures_[l,r)/bit.hpp:12
6465
ctuOneDefinitionRuleViolation:../library/data_structures_[l,r)/lazy_seg_tree.hpp:4
6566
mismatchingContainerExpression:../library/trees/extra_members/virtual_tree.hpp:19

0 commit comments

Comments
 (0)