Reputation: 17679
I have two priority_queues
- a minheap
and a maxheap
:
priority_queue<int> maxheap;
priority_queue<int, vector<int>, greater<int>> minheap;
Later in the code, I need to pop()
from whichever heap is larger:
(maxheap.size() > minheap.size() ? maxheap : minheap).pop()
This line generates an error:
error: incompatible operand types ('priority_queue<[2 * ...], (default) std::less<int>>' and 'priority_queue<[2 * ...], greater<int>>')
Apparently due to the different comparator making maxheap
and minheap
's type different.
Is there a way around this? Clearly these two types are highly compatible, so it's very useful to be able to treat them as the same.
Upvotes: 1
Views: 100
Reputation: 93264
Using the ternary operator requires both objects to have a common type, which is not the case because the two types you mentioned are not related (neither by inheritance, nor by being convertible to one another).
Just change your code to:
if (maxheap.size() > minheap.size())
{
maxheap.pop();
}
else
{
minheap.pop();
}
Clearly these two types are highly compatible
These two types satisfy a simple concept of exposing a .pop()
method, but they're not related.
so it's very useful to be able to treat them as the same
Templates and concepts can help you with that, but there's no shorthand notation for a tiny template that behaves like a ternary operator. The best you can get is:
pick(a, b, [](const auto& a, const auto& b)
{
return a.size() > b.size();
},
[](auto&& x)
{
x.pop()
});
Where pick
is something like (rough, needs forwarding and untested):
template <typename A, typename B, typename Predicate, typename F>
void pick(A&& a, B&& b, Predicate&& predicate, F&& f)
{
if (predicate(a, b))
{
f(a);
}
else
{
f(b);
}
}
But the amount of boilerplate defeats the purpose.
Upvotes: 11