首页 > 解决方案 > 为什么使用自定义比较器交换相同类型的标准库容器时会发生此错误?

问题描述

我在这段代码上遇到了编译错误。我不明白为什么当我只是添加自定义比较器时我的编译器会抛出错误。

using P = pair<int, int>;
auto comp = [](auto&l, auto&r) {
    return l.second > r.second;
};
priority_queue<P, vector<P>, decltype(comp)> pq1(comp), pq2(comp);
pq1.swap(pq2); // error!

错误就像

In file included from /opt/wandbox/gcc-10.1.0/include/c++/10.1.0/queue:64,
                 from /opt/wandbox/gcc-10.1.0/include/c++/10.1.0/x86_64-pc-linux-gnu/bits/stdc++.h:86,
                 from prog.cc:1:
/opt/wandbox/gcc-10.1.0/include/c++/10.1.0/bits/stl_queue.h: In instantiation of 'void std::priority_queue<_Tp, _Sequence, _Compare>::swap(std::priority_queue<_Tp, _Sequence, _Compare>&) [with _Tp = std::pair<int, int>; _Sequence = std::vector<std::pair<int, int> >; _Compare = main()::<lambda(auto:23&, auto:24&)>]':
prog.cc:10:13:   required from here
/opt/wandbox/gcc-10.1.0/include/c++/10.1.0/bits/stl_queue.h:696:6: error: no matching function for call to 'swap(main()::<lambda(auto:23&, auto:24&)>&, main()::<lambda(auto:23&, auto:24&)>&)'
  696 |  swap(comp, __pq.comp);
      |  ~~~~^~~~~~~~~~~~~~~~~

还有更多。

@NathanOliver,感谢您提供的信息!我为上面的示例创建了三个解决方法。

int main() {
    using P = pair<int, int>;
    auto comp = [](auto&l, auto&r) {
        return l.second > r.second;
    };
    priority_queue<P, vector<P>, function<bool(P&, P&)>> pq1(comp), pq2(comp);
    pq1.swap(pq2);
    return 0;
}
int main() {
    using P = pair<int, int>;
    function<bool(P&, P&)> comp = [](auto&l, auto&r) {
        return l.second > r.second;
    };
    priority_queue<P, vector<P>, decltype(comp)> pq1(comp), pq2(comp);
    pq1.swap(pq2);
    return 0;
}
using P = pair<int, int>;
class Comp {
public:
    bool operator()(P& l, P& r) {
        return l.second > r.second;
    }
};

int main() {
    priority_queue<P, vector<P>, Comp> pq1, pq2;
    pq1.swap(pq2);
    return 0;
}

标签: c++lambdaswapc++-standard-library

解决方案


预 C++20

闭包(lambda 表达式创建的)不可复制/移动分配。为了交换一些东西,它需要是可复制/移动可分配的,因为它不是,所以在为比较器使用闭包类型时代码将失败。

C++20

非捕获 lambda 是可复制分配的,因此如果您使用 C++20 作为编译标准,则此代码现在可以工作。


推荐阅读