11

我今天做了一些黑客攻击,发现 std::priority_queue 没有clear()成员函数。为什么标准委员会可能忽略了这一点,是否有任何技术原因?

需要明确的是,我知道通过分配很容易解决这个问题:

oldPQ = std::priority_queue<int>{};

此解决方案不太理想,因为:

  1. 它需要您重复类型 - 这在维护下不会继续工作。正如@chris 在下面指出的那样,如果您使用默认构造函数,则可以简化此操作,但如果您有自定义比较器,则这可能是不可能的。
  2. std::priority_queue不能在需要clear()成员函数的模板化函数中使用。
  3. 一般不满足其他容器提供的通用接口是不可取的。特别是,从std::forward_liststd::unordered_map到的一切std::string都有clear()。我注意到的唯一其他例外是​​ std::array ,其语义没有意义,and std::stack,当无需任何额外努力即可工作std::queue时,语义更值得怀疑。std::deque

一个看起来像问题,但实际上不一定是:因为用于的内部容器std::priority_queue是模板化的,并且可能没有自己的clear()成员函数,这产生了一个有趣的问题,特别是它提出了向后兼容性的问题. 这不是问题,因为:

  1. 对于不提供的内部容器,clear()只要没有人尝试调用std::priority_queue::clear(),代码就会继续编译。
  2. SFINAE 仍然可以通过clear()在内部容器可用时调用内部容器并在不可用时重复弹出来提供新接口(clear 成员)。

我认为这是 C++ 标准中的一个缺陷。假设技术讨论没有为为什么省略此方法提供强有力的案例,我打算继续创建标准提案。

编辑:

似乎这正在委员会内处理(注意最后一篇文章):https ://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-discussion/clear/std-discussion/_mYobAFBOrM /ty-2347w1T4J

http://wg21.cmeerw.net/lwg/issue2194

4

1 回答 1

6

众所周知,容器适配器的规范过于迂腐:由于相应数据结构的“抽象”规范(来自一些关于抽象算法和数据结构的书)不包括规范优先级队列或堆栈的操作清除,因此未提供在适配器中。这确实经常使在实践中使用这些适配器非常不方便。

不过好消息是内部容器成员在适配器内部被声明为适配器的受保护成员,名为c. 这可能是专门为您能够轻松实现自己的适配器版本而完成的:通过从标准适配器继承并添加您想要添加的任何成员函数,包括clear.

至于将这些适配器的接口与标准容器接口进行比较……我认为这不是一个有效的比较。这些适配器从未打算在接口方面与容器兼容。恰恰相反,这些适配器的目的主要是限制数据结构的公共接口,并迫使它进入其规范抽象定义所允许的狭窄范围内。

例如,不允许您迭代规范堆栈。根据定义,堆栈不是“可迭代的”。堆栈适配器禁用迭代接口的事实是一件好事。但是缺少clear肯定感觉太迂腐了,因为它具有很大的实用价值,而且看起来不像是对规范接口的严重违反。

于 2013-10-03T18:47:45.290 回答