我需要将派生的比较器传递给std :: priority_queue,但由于某种原因,正在调用基类’operator().
class Base { public: virtual bool operator() (int l,int r) const { cout << "Should not be called" << std::endl; return 0; } virtual ~Base() {} }; class A : public Base { public: bool operator() (int l,int r) const override { cout << "Should be called!!!!"; return l < r; } }; int main() { priority_queue<int,vector<int>,Base> pq((A())); pq.push(1); pq.push(2); pq.push(3); pq.push(0); cout << pq.top(); return 0; }
The code is available on ideone as well
请注意,我不能使用priority_queue< int,vector< int>,A>,因为我有Base的其他子类,这将导致大量代码重复1.
我究竟做错了什么?如何将比较器传递给将在其生命周期内使用的priority_queue?
(1)我知道我可以通过使用接受priority_queue< int,T>的模板函数来绕过代码复制问题. – 但我真的不愿意.
解决方法
该标准指定比较comp作为23.6.4.1中类模板的值成员.据说构造函数:
Initializes comp with x and c with y (copy constructing or move
constructing as appropriate);
因此你有切片,即使参数类型实际上是一个const比较& ;.
要解决这个问题,你可以为比较器实现一个pimpl-wrapper.这个包装器将在内部保持Base&到实际的比较器,在它的非虚拟运算符()中只需调用Base / A比较器的虚拟运算符().
请仔细考虑A对象的生命周期.根据比较器所需的状态,您可以在Base中实现virtual clone
-method.并将Base保留为std :: unique_ptr< Base>在你的PimplCompare中 – 你克隆它的副本.或者你把它保存为std :: shared_ptr< Base>.