我是否需要知道算法的代码才能利用插入器并移动迭代器?

Alw*_*ing 4 c++ stl c++11

C++ Primer(第5版)通过将一个insertermove iterator一个常规迭代器传递给一个std通用算法,给出了一些实现好效果的例子.

但是,我怀疑能够做到这一点取决于算法工作的内部知识,即它对迭代器参数的确切作用.这更加严重move inserter,因为我们需要确保在移动对象后不会访问它.

我的怀疑是否合理?如果是,那么标准库如何采用一种方法,要求客户(我)知道提供者的内部(STL)?

наб*_*эли 7

不,你不需要知道implememtation任何STL算法,因为他们有他们的总体要求,在国际标准规定.例如,std::remove()声明为:

template<class ForwardIterator, class T>
ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value);
Run Code Online (Sandbox Code Playgroud)

并描述如下:

template<class ForwardIterator, class T>
ForwardIterator remove(ForwardIterator first, ForwardIterator last, const T& value);
Run Code Online (Sandbox Code Playgroud)
  • 要求:类型*first应满足MoveAssignable要求(表22).
  • 效果:消除迭代器引用的所有元素i,其范围[first,last)包含以下相应条件:*i == value.
  • 返回:结果范围的结尾.
  • 备注:稳定(17.6.5.7).
  • 复杂性:确切地last - first应用相应的谓词.
  • 注意:在范围内的每个元件[ret,last),其中ret是返回值,具有有效的,但是未指定的状态下,由于算法可以通过从最初在该范围内的元素移动消除元件.

所以,你永远都需要知道的是国际标准的有关算法的段落,因为它(且仅限于它)指定究竟是什么在特定算法进行,没有多,不会少.

此外,在大多数情况下,阅读STL内部结构并不是一个好主意.

  • 插入器是输出迭代器,它们不满足前向迭代器的要求,因此这是未定义的行为,但这不是插入器的错误.如果将插入器传递给期望输出迭代器的算法,它将正常工作. (5认同)
  • `insert_iterator`是[OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator)并且有[interface](http://en.cppreference.com/w/cpp/iterator)/insert_iterator)像任何其他输出迭代器一样. (3认同)
  • @MeirGoldenberg"从不明确告诉你"与"永不告诉你"不同.标准往往不够明确.它说明了对显式传递的迭代器的要求是什么(通常是迭代器类别).它说明了`insert_iterator`满足的属性(包括迭代器类别).如果您了解迭代器类别,则可以计算出`insert_iterator'可以填充哪些参数.即使您阅读了实现,编译器版本之间也可以*变化*,而规范则不然. (2认同)

Jon*_*ely 6

您似乎对标准库中算法规范的样式感到困惑.

也许您应该从标准模板库简介开始, 它解释了STL的重点在于它是根据通用概念编写的,而不是针对每种可能的不同参数类型所发生的具体情况.这是通用编程的基础.

如果指定的算法接受为OutputIterator概念建模的参数,则表示算法将仅使用对OutputIterators有效的操作.算法的规范将告诉你它的作用,例如copy说:

对于n来自0to的每个整数last - first,copy执行赋值*(result + n) = *(first + n)

所以这告诉你算法将使用赋值运算符.

A std::insert_iterator是OutputIterator概念的模型,因此您可以将其与适用于OutputIterators的算法一起使用.如果算法的规范告诉你它将分配给它的OutputIterator参数,那么你知道会发生什么,因为规范std::insert_iterator告诉你什么赋值意味着什么std::insert_iterator.您不需要查看算法的代码就可以知道这一点,因为算法的描述和其签名中指定的概念告诉您它将使用哪些操作(并且它们只是概念支持的操作)这个需要).

在今天的C++中,算法使用的概念仅通过命名模板参数来指示所需的概念,例如,非正式地陈述

template<class ForwardIterator, class T>
ForwardIterator 
remove(ForwardIterator first, ForwardIterator last, const T& value);
Run Code Online (Sandbox Code Playgroud)

按照惯例(以及25.1 [algorithms.general]第5段中的规定),这意味着remove算法需要其前两个参数的类型来对ForwardIterator概念进行建模.

在未来的C++版本中,您可以在语言中明确说明这些要求,例如

template<class FI, class T> requires Forward_iterator<FI>
FI 
remove(FI first, FI last, const T& value);
Run Code Online (Sandbox Code Playgroud)

或等效地:

template<Forward_iterator FI, class T>
FI
remove(FI first, FI last, const T& value);
Run Code Online (Sandbox Code Playgroud)

使用这种声明样式将使所有编译器检查函数的参数是否确实满足ForwardIterator的所有要求,否则拒绝该程序.