Список генераторов со стандартной библиотекой С++?

Включает ли стандартная библиотека C++ какой-либо механизм для создания итерируемого диапазона, подобного списку, который использует встроенную функцию генератора для возврата значения в каждой позиции? то есть что-то, что могло бы дать поведение, аналогичное yield return C# или yield списков F#? Идеалом было бы:

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);

Я мог бы написать свой собственный итератор, но это кажется большой работой по сравнению с простой передачей простой лямбды в конструктор. И, конечно же, я мог бы сам написать бинарный поиск (но что в этом интересного?). Это единственные варианты?

Для потомков, вот пара ссылок, которые я нашел по этому вопросу:

Эквивалентный шаблон генератора C++ для Python

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

Но, кажется, ответ заключается в том, что нет более простого способа сделать это, чем просто написать бинарный поиск.


person dlf    schedule 06.05.2014    source источник
comment
Это не кажется мне чем-то, для чего вообще следует использовать контейнер. Скорее похоже на математический или логический процесс.   -  person John Dibling    schedule 06.05.2014
comment
@Джон Ты прав. Я пытаюсь получить итераторы по выходному пространству функции, чтобы я мог использовать алгоритмы стандартной библиотеки для ее поиска. Я отредактирую слово контейнер из вопроса.   -  person dlf    schedule 06.05.2014
comment
это похоже на то, что вы спрашиваете: stackoverflow .com/questions/12511711/ также вы можете проверить: en. cppreference.com/w/cpp/algorithm/generate_n   -  person Pedrom    schedule 06.05.2014


Ответы (3)


Алгоритмы не дадут вам индекс при сканировании диапазона. Вы можете использовать boost.Iterator (или Boost.range), чтобы помочь вам написать свой итератор (например, [boost::iterator_facade][1] или [boost::function_input_iterator][2])

person Qassim    schedule 06.05.2014
comment
+1, Boost.Iterator делает это задача легкая. - person JBentley; 06.05.2014
comment
@JBentley похоже, что я мог бы получить то, что хочу, объединив counting_iterator (что лениво) с transform_iterator. И хотя строгий логик не согласился бы, основываясь на том факте, что boost добавил их, я приду к выводу, что нет простого способа получить такое поведение, используя только стандартную библиотеку. - person dlf; 06.05.2014

Это может сработать

template<int X >       
class ListGenerator
{
  public:
    int operator[](int Y){ return X*Y;}
};

int main()
{
    ListGenerator<5> lg;
    cout<<lg[5]<<endl;
    return 0;
 }

вы можете изменить список параметров шаблона, чтобы добавить столько, сколько вам нужно.

person Rakib    schedule 06.05.2014
comment
Что-то подобное даст мне семантику [], но не итераторы, которые мне понадобятся для использования алгоритмов стандартной библиотеки. - person dlf; 06.05.2014

Что-то вроде этого?

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

Здесь мы заполняем список элементами count из нашей функции-генератора (лямбда).

person paxos1977    schedule 06.05.2014