如何在没有显式比较对象的情况下从 Container 对象构造 std::priority_queue 的实例?

Posted

技术标签:

【中文标题】如何在没有显式比较对象的情况下从 Container 对象构造 std::priority_queue 的实例?【英文标题】:How do I construct an instance of std::priority_queue from a Container object without an explicit Compare object? 【发布时间】:2021-07-06 11:42:51 【问题描述】:

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

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

现在假设我对这些默认值非常满意,并希望从现有的 std::vector&lt;int&gt; 对象构造一个 std::priority_queue&lt;int&gt; 对象。

我can最接近的是

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

它使用cont 移动构造底层容器,然后通过调用std::make_heap 对其进行堆化。

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

std::vector<int> vec;
// filling vec with values
std::priority_queue<int> pqstd::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())  

还是我错过了其他方法?

【问题讨论】:

没有。 std::priority_queue 在几个方面违反了最小惊讶原则。但这是很棒的课程,“std::less()”的那 16 个字符并不算多。在 C++ 中,最安全和最有效的规则是最冗长的。你有没有注意到省略“const&”会如何破坏性能?这就是为什么。 【参考方案1】:

我认为您的要求是合理的,我也在考虑用例,但遗憾的是 STL 不支持它。然后我们可以考虑制作自己的包装器:我们只是继承priority_queue,并进行强制转换:

#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>());

用法会很干净:

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

Online demo

【讨论】:

以上是关于如何在没有显式比较对象的情况下从 Container 对象构造 std::priority_queue 的实例?的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有 Linq 的情况下从列表中获取一些对象?

如何在没有动画的情况下从集合视图中删除项目?

JSON.NET:如何在没有数组的情况下从DataTable对象中仅序列化一行?

在没有第三方库的情况下从 JSON 获取动态对象的最佳方法是啥?

如何在不通过 COM 的情况下从 VB6 调用 C++ DLL?

是否可以在没有画布的情况下从 ImageBitMap Web 对象中获取像素?