【发布时间】:2020-04-25 19:38:14
【问题描述】:
1.
现行标准草案中std::stable_partitionis的规范:
template<class BidirectionalIterator, class Predicate> BidirectionalIterator stable_partition( BidirectionalIterator first, BidirectionalIterator last, Predicate pred);
我没有发现(见下文)BidirectionalIterator 应该是双向迭代器的要求,但顾名思义。
2. 在 SGI STL 中,规范is:
template <class ForwardIterator, class Predicate> ForwardIterator stable_partition( ForwardIterator first, ForwardIterator last, Predicate pred);类型要求:
ForwardIterator是Forward Iterator的模型。
当前标准和 SGI 版本的复杂性规范是相同的:最多 N log N 交换,如果有足够的额外内存并且恰好 N 谓词和投影的应用程序,则只有 O(N) 交换。
template<typename ForwardIterator, typename Predicate>
ForwardIterator stable_partition(
ForwardIterator first, ForwardIterator last, Predicate pred);
在 GCC 和 Clang 中,std::stable_partition 确实适用于前向迭代器。例如:
int main() {
std::forward_list<int> list{1, 4, 5, 2, 3, 0};
std::stable_partition(list.begin(), list.end(), [](int i) { return i < 3;});
for (auto v : list)
std::cout << v << ' ';
}
compiles and produces the correct output。 Microsoft 的编译器无法编译此代码(没有-- 运算符)。英特尔的成功了。
我有两个相关的问题:
std::stable_partition是否至少接受标准的双向迭代器或名称BidirectionalIterator具有误导性?- 如果它确实只接受双向迭代器,为什么不再支持前向迭代器?
编辑。
找到this clause:
如果算法的模板参数命名为
BidirectionalIterator、BidirectionalIterator1或BidirectionalIterator2,则模板参数应满足Cpp17BidirectionalIterator的要求。
所以,只剩下第二个问题了。
【问题讨论】:
-
可能相关:stackoverflow.com/questions/21554635/… 如果是实现效率的问题,
std::reverse也仅限于双向迭代器。 -
@Bob__ 感谢您的链接。但是这里讨论的“慢”和“快”版本之间的选择与额外内存缓冲区的可用性有关,但与迭代器类别无关。
-
当然,但该标准还要求在交换方面具有一定的复杂性。在前面关于
partition的行中,在 25.7.4.8 中它说 “如果 first 的类型满足命名空间 std 或模型 bidirectional_iterator 中的重载的 Cpp17BidirectionalIterator 要求,则最多交换 N/2用于命名空间范围内的重载,否则最多交换 N 个。”。所以也许需要一个双向迭代器来确保25.7.4.13的要求。 -
@Bob__ 支持前向迭代器的 SGI STL 与不支持前向迭代器的标准库具有相同的复杂性规范。
-
FWIW,即使在 C++98 中它已经需要
BidirectionalIterator: lirmm.fr/~ducour/Doc-objets/ISO+IEC+14882-1998.pdf