我需要将派生的比较器传递给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>.