c++ - 生成具有迭代器行为的仿函数

标签 c++ iterator generator functor

我有一个问题,很可能以前有人这样问过,因为我认为我想要的是相当多的人想要的东西。但是我想不出任何表达它的方式来返回我在搜索中想要的东西(不是谷歌,不是这里)。所以也许这里的答案只是一个用来描述我的意思的术语。

我想要实现的是大致执行以下操作的内容:

  1. 它可以采用仿函数结构/类并生成一系列值 对于基于仿函数函数的所述仿函数。应该可以使用有状态的仿函数,即应该可以在状态 a 中实例化一个仿函数并让它运行直到它处于状态 b,生成值的范围 {f(a), f(a+1) , ..., f(b)},其中f(a+1)表示f所代表的系列中的下一项。

  2. 它的行为类似于迭代器,即它可以代替迭代器传递,例如用值填充 vector 。

我认为名称应该是生成器或生成迭代器,因为它就是这样做的,但我一直没有找到与该术语相关的东西。我已经编写了自己的实现,但它有它的问题,我想问一下,在投入更多精力之前是否有这样的事情。

为了让您省去粘贴所有后续代码的工作,以防您想尝试这个,我把它放在了 ideone 上。 .我认为在运行代码后,它的作用就很清楚了。

我当前的实现看起来像这样(仅供引用,这是一个缩短的版本,其中缺少一些像 -- 和 - 这样的东西,所以是的,我确实实现了它们,因此它至少可以作为双向迭代器工作。我还有一个[] 函数,所以我考虑让它成为 random_access。):

template <class F>
class generator{
public:
//typedefs required for iterator-use
typedef typename F::value_type value_type;
typedef typename F::step_type step_type;
typedef value_type * pointer;
typedef value_type & reference;
typedef typename F::size_type size_type;
typedef typename F::difference_type difference_type;
typedef std::bidirectional_iterator_tag iterator_category;

generator(value_type init, step_type step) : t(init), step(step){}

generator<F> &operator++() {
    t += step; return *this;
}

generator<F> &
operator+=(size_type n)
{
    t += n * step;
    return *this;
}

generator<F>
operator+(size_type n)
{
    return generator(*this) += n;
}

value_type operator*() const {
    return f(t);
}

value_type operator*() const {
    return f(t);
}

friend bool operator==(const generator<F> &lhs, const generator<F> &rhs){
    return lhs.t == rhs.t;
}
friend bool operator!=(const generator<F> &lhs, const generator<F> &rhs){
    return !(lhs == rhs);
}
private:
    value_type t;
    value_type step;
    F f;
};

我使用不同的模板来尽可能轻松地提供 typedef:

template <typename T>
struct simple_generator_function
{
    typedef T value_type;
    typedef T step_type;
    typedef T difference_type;
    typedef size_t size_type;
};

现在这两者与一个像这样的具体“生成器”一起工作:

template <typename T>
struct square_generator : public simple_generator_function<T> {

    T operator()(T t) const{
        return t * t;
    }
};

int main(void) {
    using int_sqg = generator<square_generator<int>>;
    //starting at initial value 1 take steps of size 4
    int_sqg gen(1, 1);
    //fill with all before inital + n * step
    vector<int> v(gen, gen+10);
    copy(begin(v), end(v), ostream_iterator<int>(cout, ","));
    cout << '\n';
}

长话短说:是否有 boost 或其他库以某种可靠的方式提供此功能,这种迭代器/仿函数混合的一般名称是什么?

编辑 1:

我认为任何解决方案最多只能是一个 InputIterator,因为据我研究,所有其他迭代器都必须从 operator*(),在这种情况下这是不可能的。很可能,它归结为编写一个模板,将常规仿函数转换为 InputIterator。

状态:目前的答案都很好,但是我在问这个问题之前思考了很久,也想过类似的解决方案,所以我的问题没有得到真正的回答。我已经更新了要求 1.) 以 - 希望 - 更清楚地反射(reflect)我想要什么。如果没有任何结果,我可能会尝试将我当前的代码改进为更稳定的版本并将其放在 github 上。

编辑 2(赏金结束):

尽管我对解决方案并不完全满意,但按照 ectamur 的建议,boost::irange 与 boost::transformed 的结合最接近我想做的事情,所以我会赏金给他。

最佳答案

Boost.Range 解决这个问题的方法是使用transform 迭代器适配器:

auto rng = boost::irange(1, 10)
    | boost::adaptors::transformed([](int i) { return i * i; });
std::vector<int> v{rng.begin(), rng.end()};

请注意这是如何将转换的关注点与输入范围的开始/停止/步骤(可选)参数分开的。

关于c++ - 生成具有迭代器行为的仿函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28263134/

相关文章:

c# - 如何创建具有生成名称的对象?

python - 带有 Tensorflow 数据集 API 的 Keras 生成器 - IndexError : pop from empty list

c++ - #error 指令中是否允许使用非拉丁字符?

javascript - JS中真正的数组和数组迭代器有什么区别

c++ - find_if 找到一个不等于某物的元素

c++ - iterator_traits<vector<bool>::iterator>::iterator_category 不应该是 input_iterator_tag 吗?

generics - 如何在 Swift 中返回一个序列?

c++ - 我可以将 nullptr 转换为其他指针类型吗?

c++ - C++ 中的空指针

c++ - 将 MFC Cimage 初始化为纯色