C++ Primer(第5版)通过将一个inserter或move iterator一个常规迭代器传递给一个std通用算法,给出了一些实现好效果的例子.
但是,我怀疑能够做到这一点取决于算法工作的内部知识,即它对迭代器参数的确切作用.这更加严重move inserter,因为我们需要确保在移动对象后不会访问它.
我的怀疑是否合理?如果是,那么标准库如何采用一种方法,要求客户(我)知道提供者的内部(STL)?
不,你不需要知道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内部结构并不是一个好主意.
您似乎对标准库中算法规范的样式感到困惑.
也许您应该从标准模板库简介开始, 它解释了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的所有要求,否则拒绝该程序.