C++ 无法将派生的比较传递到std::priority\u队列
我需要将派生的比较器传递给C++ 无法将派生的比较传递到std::priority\u队列,c++,c++11,std,priority-queue,C++,C++11,Std,Priority Queue,我需要将派生的比较器传递给std::priority\u queue,但由于某种原因,正在调用基类的运算符() 下面是显示此行为的最基本代码: class Base { public: virtual bool operator() (int l, int r) const { cout << "Should not be called" << std::endl; return 0; } virtual ~
std::priority\u queue
,但由于某种原因,正在调用基类的运算符()
下面是显示此行为的最基本代码:
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;
}
类基{
公众:
虚拟布尔运算符()(int l,int r)常量{
cout构造函数接受一个常量比较&
,当将对象传递给函数时,它不会导致任何切片,但是我们在
Copy使用cont的内容构造底层容器c。Copy使用compare的内容构造比较函子comp
由于正在进行复制且模板类型为Base
,因此您只需复制并存储a
对象的Base
部分
您必须将比较对象包装在某种包装器中,并公开一个非虚拟的操作符()
,该操作符将调用虚拟的操作符()
传递给优先级队列的类型
构造函数。标准规定比较comp
为23.6.4.1中类模板的值成员。构造函数被称为:
用x初始化comp,用y初始化c(复制或移动
(视情况而定)
因此,即使参数类型实际上是一个const Compare&
,也有切片
为了解决这个问题,您可以为比较器实现一个pimpl包装器。这个包装器将在内部为实际比较器保留一个基&
,在它的非虚拟操作符()
中,只需调用基
/比较器的虚拟操作符()
请仔细考虑A
对象的生存期。根据比较器所需的状态,您可以在Base
中实现一个,并将Base
作为std::unique\u ptr
保存在pimplpcompare
中,您可以将其克隆到它的副本中。或者将其作为std::shared\u ptr
.@πνταῥεῖ 为什么要切片?构造函数正在接受const Compare&
。我不愿意相信它以后会在std库类中以值保存。很抱歉,en.cppreference.com暂停了一会儿。@amit它必须在内部以值保存。如果容器只是保存引用,那么问题中的代码将是未定义的行为因为当构造函数调用返回时,传递给容器的比较器实例的生存期就结束了。当然,它是按值保存的。“您只需要复制和存储对象的基本部分。”这不正是切片吗?问题是“我做错了什么?”。或者更明确地说,我如何将比较器传递给将在其生命周期内使用的优先级_队列?@πάνταῥεῖ 我重新编写了它,以澄清我的意思是在传递给函数时它不是切片。我相信当它声明为(2)“Move用std::Move(compare)构造比较函子comp时是错误的。在所有构造函数中,compare由const comp&
std::Move(compare)
的类型为const Comp&&
,但move构造函数将采用Comp&&
,因此它将调用复制构造函数。libstdc++似乎不会在比较器上进行任何移动。