Boost C++ 库

……世界上最受推崇且设计最专业的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu,《C++ 编码规范

- Boost C++ 函数库
作者 Dean Michael Berris
License在 Boost 软件许可协议版本 1.0 下分发(请参阅附带的 LICENSE_1_0.txt 文件或访问 https://boost.ac.cn/LICENSE_1_0.txt

函数输入迭代器 (Function Input Iterator)

函数输入迭代器允许创建封装了零元函数对象 (nullary function object) 和状态对象的迭代器,该状态对象用于跟踪迭代器自增的次数。函数输入迭代器对 InputIterator(输入迭代器)概念进行建模,对于创建有界输入迭代器非常有用。

与生成器迭代器一样,函数输入迭代器采用一个对 Generator(生成器)概念进行建模的函数(本质上是一个零元或 0 元数函数对象)。函数输入迭代器的每次自增都会调用生成器函数并将该值存储在迭代器中。当对迭代器解引用时,将返回存储的值。

函数输入迭代器封装了一个对 可递增概念 (Incrementable Concept)EqualityComparable(相等比较)概念进行建模的状态对象。这些概念描述如下:

可递增概念 (Incrementable Concept)

当一个类型支持前置和后置自增运算符时,该类型即对“可递增概念”进行建模。对于给定对象i类型为I,以下构造应有效:

构造 描述 返回类型
i++ 后置自增 i++ I
++i 前置自增 ++i I&

注意:可递增类型还应满足 DefaultConstructible(默认可构造)。

提要

namespace {
    template <class Function, class State>
    class function_input_iterator;

    template <class Function, class State>
    typename function_input_iterator<Function, State>
    make_function_input_iterator(Function & f);

    struct infinite;
}

函数输入迭代器类

函数输入迭代器类采用两个模板参数函数andState。这两个模板参数告诉函数输入迭代器所封装的函数类型以及要持有的内部状态值的类型。

State参数在需要控制计数器类型(该计数器决定了两个迭代器是否处于相同状态)的情况下非常重要。这允许创建一对迭代器,用于限定封装函数的调用范围。

示例

以下示例展示了当我们想要创建有界(惰性)生成范围时,如何使用函数输入迭代器类。

struct generator {
    typedef int result_type;
    generator() { srand(time(0)); }
    result_type operator() () const {
        return rand();
    }
};

int main(int argc, char * argv[]) {
    generator f;
    copy(
            make_function_input_iterator(f, 0),
            make_function_input_iterator(f, 10),
            ostream_iterator<int>(cout, " ")
        );
    return 0;
}

这里我们可以看到,我们使用了一个int来限制调用的次数,该计数器从010开始计数。假设我们想创建一个无穷大的随机数流并将其封装在一对整数中,我们可以使用boost::infinite辅助类来实现。

copy(
        make_function_input_iterator(f,infinite()),
        make_function_input_iterator(f,infinite()),
        ostream_iterator<int>(count, " ")
    );

在上面,我们没有创建一个巨大的向量,而是依赖 STL 的 copy 算法来遍历函数输入迭代器,并在迭代器自增时调用函数对象 f。special 属性的boost::infinite是,比较两个实例的结果总是为 false——并且自增boost::infinite的实例不会执行任何操作。这是一种有效的方法,用以说明由两个具有封装无穷状态的迭代器所提供的迭代器范围肯定是无限的。