willem
willem

Reputation: 2717

How to output a sequence one by one based on custom logic?

I have a class that uses custom logic to generate some sequence:

class Example{
   size_t FirstElement();
   size_t NextElement(size_t currentelement);
   //When element equals magic number this is 
   //signalling that the sequence is over.  
   static size_t MagicNumber =-1;     
}

I could consume the sequence as follows:

Example example{};
for(size_t curelement = example.FirstElement; 
             curelement != Example::MagicNumber;
               curelement = example.NextElement(currentelement))
{
      //do something with the curelement
}

I would like a solution which makes it similarly easy to consume the sequence, but:

Is there a good alternative. (Based on my (very limited) understanding of iterators, they should be the goto solution here? If so, how to implement such a solution?)

Upvotes: 1

Views: 84

Answers (2)

acraig5075
acraig5075

Reputation: 10756

A for-loop is fine for iterating your class. You just seem to want it to be generic in how it terminates and presumably what the body does. Seems like overkill but this is a solution.

void Consume(Example &example, std::function<bool(Example)> terminateFunc, std::function<void(Example)> bodyFunc)
{
    for(size_t curelement = example.FirstElement; !terminateFunc(curelement); curelement = example.NextElement(curelement))
    {
        bodyFunc(curelement);
    }
}

i.e. terminateFunc and bodyFunc are passed in, and can be custom for whatever conditions you require.

auto condition = [](Example e) { return true; /* check if e satisfies some condition; */ };
auto body = [](Example e) { /* do something with e */ };

Consume(example, condition, body);

Upvotes: 0

Lukas-T
Lukas-T

Reputation: 11340

Yes, I would advise you to use iterators. They usually work the same way, like your code:

Example e;
for(auto it = e.begin(); it != e.end(); ++it)
{...}

//Can be simplified to 
for(const auto &x : e)
{...}

where begin() will return the iterator pointing to the first element (like Example::FirstElement(). and end() the iterator to the element after the last (This could return your magic number). However...both values should be wrapped in a class and you should not just return integers as iterators.

For further reading I would suggest this and this post.

Upvotes: 1

Related Questions