【问题标题】:custom comparator without default constructor as template parameter没有默认构造函数作为模板参数的自定义比较器
【发布时间】:2020-02-04 12:19:47
【问题描述】:

让我们看一个从两个排序数组中找到最小的m 数字对的玩具示例。 抛开算法效率问题不谈,我想为优先级队列提供一个比较器 在初始化过程中需要某些参数:

class Foo {
    struct natural_order {
        const std::vector<int> &x,&y;
        natural_order( const std::vector<int> &x, const std::vector<int> &y ): x(x), y(y) {};
        bool operator () ( const std::pair<int,int> &a, const pair<int,int> &b ) const {
            return x[a.first]+y[a.second] < x[b.first]+y[b.second];
        }
    };
    struct cmp {
        std::unique_ptr<natural_order> o;
        cmp( const std::vector<int> &x, const std::vector<int> &y ) {
           o= std::make_unique<natural_order>(x,y);
        }
        bool operator () ( const std::pair<int,int> &a, const pair<int,int> &b ) const {
            return (*o)(b,a);
        }
    };
public:
    std::vector<std::vector<int>> m_smalles_pairs( std::vector<int> &x, std::vector<int> &y, int m ) {
        std::vector<std::vector<int>> res(m);
        std::priority_queue<int,std::vector<int>,cmp(x,y)> pq; //<-- the problem is here. Does not compile
        for ( int i= 0; i < m; ++i ) {
            auto pr= pq.top(); pq.pop();
            res[i]= std::vector<int>{x[pr.first],y[pr.second]};
            if ( pr.first+1 < x.size() )
                pq.push({pr.first+1,pr.second});
            if ( pr.second+1 < y.size() )
                pq.push({pr.first,pr.second+1});
        }
        return res;
    }
};

本质上,我希望使用一个参数来初始化比较器,但是如何将它作为priority_queue 的第三个参数提供呢?如果不需要xy 参数,我会在上面简单地写cmp

编辑:它似乎使用 lambda 以类似的方式进行,如此处所述C++ priority_queue with lambda comparator error 我能够解决我的问题,但只是好奇struct-comparator 是否允许这种事情。

【问题讨论】:

    标签: c++ priority-queue


    【解决方案1】:

    基本上,您的代码的问题在于 Compare 的实现。 从技术上讲,Compare-class 必须满足一些要求:

    类型 T 满足 BinaryPredicate ---> CopyConstructible

    您的类cmp 不是可复制构造,因为它的成员之一是std::unique_ptr(它不能被复制)。

    所以我想说一个合适的解决方案应该是按照这个原则重构你的设计。 我不了解您的问题的全部领域,因此我无法建议正确的设计(而且这可能是个人选择)。

    也许,您可以从您的班级中删除 std::unique_ptr 并让 natural_order 类型作为成员。当然,这意味着不同的复制构造调用。

    此时,您可以使用适当的构造函数初始化 std::priority_queue 的比较器。

    (2) explicit priority_queue(const Compare& compare)
               : priority_queue(compare, Container()) { }
    

    你的代码应该是这样的:

    std::priority_queue<int,std::vector<int>,cmp> pq(cmp{x, y});
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-15
      • 1970-01-01
      • 1970-01-01
      • 2016-05-22
      相关资源
      最近更新 更多