【问题标题】:Generator list with c++ standard library?带有 C++ 标准库的生成器列表?
【发布时间】:2014-06-23 03:49:40
【问题描述】:

C++ 标准库是否包含任何机制来生成类似列表的可迭代范围,该范围使用注入的生成器函数返回每个位置的值?即可以产生类似于 C# 的 yield return 或 F# 的 yield 列表理解的行为?理想的情况是:

hypothetical_generator_list<size_t> l([](size_t index) { return index * 2; });
assert(l[4] == 8);
assert(*(l.begin() + 1000000000) == 2000000000);

动机:我想对包含数千亿(单调递增)值的空间进行二分搜索。但是std::lower_bound 需要迭代器,并且完全不可能将所有值放入像vector 这样的任何东西中。但是,我可以很容易地编写一个函数,给定一个索引,执行一些计算并返回该索引处的值。

hypothetical_generator_list<size_t> c([](size_t index) { return index * 2; });
auto itFound = std::lower_bound(l.begin(), l.begin() + 100000000000, 6000);
assert(itFound - l.begin() == 3000);

我可以编写自己的自定义迭代器,但与仅将简单的 lambda 传递给构造函数相比,这似乎需要大量工作。当然,我也可以自己编写二进制搜索(但这有什么好玩的呢?)。这些是唯一的选择吗?

为了后代,这里有几个我在这个主题上找到的链接:

Equivalent C++ to Python generator pattern

http://www.sirver.net/blog/2011/08/19/generators-in-c++/

但似乎答案是没有比编写二进制搜索更简单的方法了。

【问题讨论】:

标签: c++ iterator c++-standard-library


【解决方案1】:

这样的?

std::size_t index = 0;
std::generate_n(std::back_inserter(list), count, [&index]
{
    return index++ * 2;
});

这里我们使用生成器函数(lambda)中的 count 个元素填充列表。

【讨论】:

    【解决方案2】:

    在扫描范围时,算法不会为您提供索引。您可以使用 boost.Iterator(或 Boost.range)来帮助您编写迭代器(例如 [boost::iterator_facade][1][boost::function_input_iterator][2]

    【讨论】:

    • +1, Boost.Iterator 让这项任务变得简单。
    • @JBentley 它看起来通过将counting_iterator(这是惰性的)与transform_iterator 结合起来可以得到我想要的。尽管严格的逻辑学家会不同意,但基于 boost 添加这些的事实,我会得出结论,仅使用标准库没有简单的方法来获得这种行为。
    【解决方案3】:

    它可能会起作用

    template<int X >       
    class ListGenerator
    {
      public:
        int operator[](int Y){ return X*Y;}
    };
    
    int main()
    {
        ListGenerator<5> lg;
        cout<<lg[5]<<endl;
        return 0;
     }
    

    您可以根据需要修改模板参数列表以添加任意数量。

    【讨论】:

    • 类似的东西会给我[]语义,但不是我需要使用标准库算法的迭代器。
    猜你喜欢
    • 1970-01-01
    • 2011-09-11
    • 2015-01-16
    • 1970-01-01
    • 2016-01-04
    • 1970-01-01
    • 2012-10-28
    • 2012-04-14
    • 1970-01-01
    相关资源
    最近更新 更多