今天写树形dp,用匿名函数出现了极其玄学的报错,modernCPP给我上了一课
note: 'solve()::<lambda(auto:23, int, int)>::~
()' is implicitly deleted because the default definition would be ill-formed
源代码
void solve() {
int n;
std::cin >> n;
std::vector<int> edge[n + 1];
std::vector<int> F(n + 1);
std::vector<int> ind(n + 1);
for (int u, v, i = 0; i < n - 1; i++) {
std::cin >> u >> v;
edge[u].emplace_back(v);
edge[v].emplace_back(u);
ind[u]++; ind[v]++;
}
auto dfs = [&](auto self, int x, int father) -> void {
if (ind[x] == 1 && x != 1) {F[x] = 1; return ;}
for (auto& to : edge[x]) if (to != father) {
self(self, to, x);
F[x] += F[to];
}
return ;
};
dfs(dfs, 1, 0);
int q;
std::cin >> q;
while(q--) {
int x, y;
std::cin >> x >> y;
std::cout << F[x] * F[y] << '\n';
}
}
排查
由于报错是析构函数出错,比较难以排查,所以就枚举了所有情况,发现以下几种写法可以通过编译。
-
声明
function
类型std::function<void(int, int)> dfs [&](int x, int father) -> void { if (ind[x] == 1 && x != 1) {F[x] = 1; return ;} for (auto& to : edge[x]) if (to != father) { dfs(to, x); F[x] += F[to]; } return ; };
从声明类型后就可以通过编译我感觉是编译器在 auto 推断时出了错误,然而却并非如此。
-
注明捕获对象
auto dfs = [&ind, &edge, &F](auto self, int x, int father) -> void { if (ind[x] == 1 && x != 1) {F[x] = 1; return ;} for (auto& to : edge[x]) if (to != father) { self(self, to, x); F[x] += F[to]; ` } return ; };
这里找出了真正的原因,自动捕获到了脏东西。
解决
自动捕获到了什么脏东西?
对捕获对象逐一排查后,发现对于邻接表存图的 edge
,把大小改成常量或者使用 vector
嵌套后就能通过编译。
这里涉及了 CPP 为了兼容 C 而留下的遗留问题
VLA虽然允许存在,但是modernCPP的接口没有义务再兼容VLA
改成嵌套 vector
后即可通过
void solve() {
int n;
std::cin >> n;
std::vector<std::vector<int>> edge(n + 1, std::vector<int>());
std::vector<int> F(n + 1);
std::vector<int> ind(n + 1);
for (int u, v, i = 0; i < n - 1; i++) {
std::cin >> u >> v;
edge[u].emplace_back(v);
edge[v].emplace_back(u);
ind[u]++; ind[v]++;
}
auto dfs = [&](auto self, int x, int father) -> void {
if (ind[x] == 1 && x != 1) {F[x] = 1; return ;}
for (auto& to : edge[x]) if (to != father) {
self(self, to, x);
F[x] += F[to];
}
return ;
};
dfs(dfs, 1, 0);
int q;
std::cin >> q;
while(q--) {
int x, y;
std::cin >> x >> y;
std::cout << F[x] * F[y] << '\n';
}
}
标签:std,体会,vector,int,auto,modernCPP,ind,edge,DEBUG
From: https://www.cnblogs.com/kdlyh/p/18034430