首页 > 解决方案 > 如何在没有显式比较对象的情况下从 Container 对象构造 std::priority_queue 的实例?

问题描述

根据cppreference, std::priority_queue 被定义为三个参数的模板TContainerCompare,其中最后两个具有基于的默认值T

class Container = std::vector<T>,
class Compare = std::less<typename Container::value_type>

现在假设我对这些默认值非常满意,并希望std::priority_queue<int>从现有对象构造一个对象std::vector<int>

我能拥有的最接近的是

priority_queue(const Compare& compare, Container&& cont);

它使用移动构造底层容器cont,然后通过调用std::make_heap.

一切都很好,但我必须明确提供一个Compare对象,即

std::vector<int> vec;
// filling vec with values
std::priority_queue<int> pq{std::less<int>(), std::move(vec)};

为什么 std::priority_queue 没有像这样的构造函数

priority_queue(const Container& cont);
priority_queue(Container&& cont);

这似乎是合理的,因为它有一个仅比较器的构造函数:

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

还是我错过了其他方法?

标签: c++stlpriority-queue

解决方案


I think your requirement is reasonable and I was considering the use case too, but sadly the STL doesn't support it. Then we can consider making our own wrapper: We just inherit the priority_queue, and make a cast:

#include <iostream>
#include <queue>
#include <vector>

template <typename T, typename Seq = std::vector<T>,
          typename Cmp = std::less<typename Seq::value_type>>
class MyPriorityQueue : public std::priority_queue<T, Seq, Cmp> {
 public:
  using base_t = std::priority_queue<T, Seq, Cmp>;
  MyPriorityQueue() = default;
  template <typename Cont>
  MyPriorityQueue(Cont&& cont) : base_t(Cmp{}, std::move(cont)) {}
  template <typename Cont>
  MyPriorityQueue(const Cont& cont) : base_t(Cmp{}, cont) {}
};

template <typename Cont, typename T = typename Cont::value_type,
          typename Seq = std::vector<T>,
          typename Cmp = std::less<typename Seq::value_type>>
std::priority_queue<T, Seq, Cmp> MakePriorityQueue(Cont&& cont) {
  return std::priority_queue<T, Seq, Cmp>(
      MyPriorityQueue<T, Seq, Cmp>(std::move(cont)));
}

template <typename Cont, typename T = typename Cont::value_type,
          typename Seq = std::vector<T>,
          typename Cmp = std::less<typename Seq::value_type>>
std::priority_queue<T, Seq, Cmp> MakePriorityQueue(const Cont& cont) {
  return std::priority_queue<T, Seq, Cmp>(MyPriorityQueue<T, Seq, Cmp>(cont));
}
template <typename T, typename Seq = std::vector<T>,
          typename Cmp = std::less<typename Seq::value_type>>
std::priority_queue<T, Seq, Cmp> MakePriorityQueue() {
  return std::priority_queue<T, Seq, Cmp>(MyPriorityQueue<T, Seq, Cmp>());
}

The usage would be clean:

  std::vector<int> vec;
  auto pq = MakePriorityQueue(std::move(vec));

Online demo


推荐阅读