Something feels like a question from the series “like I didn’t have myself”, but ...

There is a generator (of numbers, but better than objects). Ideally, it somehow returns that it has finished generating (it would be nice if you could transfer the istream_iterator and lambda, let's say ...), but, reluctantly, I agree even to just quantity. Next - there is a predicate that is not sewn into the generator itself (and if it is sewn up, then we can’t say for sure how many values ​​will be generated!)

They want to filter and send somewhere.

Parts are done simply - say, generate_n into some vector (via back_inserter ), then copy_if with a predicate - say, in ostream_iterator .

Write your own code is even easier :)

But I want to pervert - through STL and without additional storage in the container. Ideally, one line (one nested call).

The feeling that something is spinning around, but something is not given ...

Here is a sample code:

 vector<int> v(1000); generate(v.begin(),v.end(),[](){.....}); copy_if(v.begin(),v.end(),[](){.....}, ostrim_iterator<int>(cout,"\n")); 

How to do the same WITHOUT an additional vector? If the number of objects generated can be very large?

generate_n not suitable for two reasons: there is no predicate in it and I do not know in advance how many objects will be generated. If I transfer the predicate directly to the generator - how to explain that everything is generated and it is time to leave the algorithm? Unless with the help of an exception, but this is a wrong decision from a design point of view.

Your code looks like this:

 int n; ostrim_iterator<int> os(cout,"\n"); while([&n](){ return true; /* false по окончании генерации*/ }) { if (pred(n)) *os++ = n; } 

Those. until it is generated, we simply check with the predicate and send it via an iterator.

I emphasize once again - I don’t have to solve the problem, I’m just wondering how to solve it, staying within the framework of the standard library, and is it possible at all? It would seem a chain

 Генератор -> Фильтр -> Выход 

should not be uncommon, so a standard library should contain its solution?

Update
I came up with an option - writing an iterator from the generator. Those. with each ++ this iterator returns the newly generated value. Then the usual copy_if . There is no such standard adapter that turns the generator into an iterator? ...

  • Frankly speaking, it’s not immediately clear from this description what you want to do. - Unick
  • Why not use std :: generate with a custom generator? - free_ze
  • @free_ze Because in this case I cannot tell from the generator that everything that is needed has been generated. Unless to generate an exception - but this is a clear crutch. generate_n not suitable for the same reason - I do not know when generation will end, i.e. how many items there will be. - Harry
  • Maybe fork + pipe? - avp
  • @avp Yes, I can easily write my own function with my hands (which I did already), the question is basically ... - Harry

1 answer 1

maybe it's worth playing with Eric Nilbert's rangeV3, after all this will become standard when https://ericniebler.imtqy.com/range-v3/ code is not possible to check, but I think to dig like this:

 //взято из тестов auto ns = view::generate([]() mutable { static int N; return ++N; }); auto rng = ns | view::take_while([](int i) { return i < 5; }); //сюда нужно вставить ваш предикат //ну и отправляем rng в std::cout: ranges::for_each(myRanges, [](auto const& r) { std::cout << r << '\n'; }); //либо вроде даже так, не помню точно: std::cout<<rng; 

if you need examples, that is, in his tests: https://github.com/ericniebler/range-v3/tree/master/test