PHP Custom Iterators - Predicate Example

AceInfinity

Emeritus, Contributor
Joined
Feb 21, 2012
Posts
1,728
Location
Canada
Here's an implementation of a predicate iterator that I wrote in C++:
Code:
[plain]#include <iostream>
#include <string>
#include <cstring>
#include <cctype>
#include <iterator>
#include <algorithm>

template <class F, class DelimT, class T>
class predicate_iterator : public std::iterator<std::output_iterator_tag, std::basic_ostream<T>>
{
  public:
    predicate_iterator(F func) : func_(func), delim_(default_delim_), os_(std::cout) { }
    predicate_iterator(F func, DelimT delim) : func_(func), delim_(delim), os_(std::cout) { }
    predicate_iterator(F func, std::basic_ostream<T> &os) : func_(func), delim_(default_delim_), os_(os) { }
    predicate_iterator(F func, DelimT delim, std::basic_ostream<T> &os) : func_(func), delim_(delim), os_(os) { }

    predicate_iterator operator ++ (int) { return *this; }
    predicate_iterator operator ++ () { return *this; }
    predicate_iterator operator * () { return *this; }
    void operator = (T obj) { if (func_(obj)) os_ << obj << delim_; }

  private:
    const std::string default_delim_ = ", ";
    std::basic_ostream<T> &os_;
    DelimT delim_;
    F func_;
};


template <class F, class DelimT, class T>
predicate_iterator<F, DelimT, T> create_predicate_iterator(F f, const DelimT delim, std::basic_ostream<T> &obj)
{
  return predicate_iterator<F, DelimT, T>(f, delim, obj);
}


std::ostream &operator <<(std::ostream &os, const char *str)
{
  auto it = create_predicate_iterator(isupper, std::string(), os);
  std::copy(str, str + strlen(str), it);
  return os;
}

int main()
{
  using namespace std;
  cout << "this is just A message to Prove that you can Print to the consoLe with prEdicate iteratorS." << endl;
}[/plain]

This example allows the iterator to take the input of each element and put it through a function that evaluates requirements for outputting to the standard output stream with the << operator. You could overload the create_predicate_iterator() function to enable type deduction for the other constructors of this iterator as well. Example:
Code:
[plain]template <class F, class T>
predicate_iterator<F, std::string, T> create_predicate_iterator(F f, std::basic_ostream<T> &obj)
{
  return predicate_iterator<F, std::string, T>(f, obj);
}[/plain]

Please note the destruction of temp variables. For that reason, this will not work:
Code:
[plain]auto it = create_predicate_iterator(isupper, ", ", os);[/plain]

But this will:
Code:
[plain]auto it = create_predicate_iterator(isupper, ',', os);[/plain]

Why? Because we are not passing a pointer to that data whose destructor was called, we are actually passing that data as a copy. In this case, the char itself.

This will work however:
Code:
[plain]auto it = create_predicate_iterator(isupper, std::string(", "), os);[/plain]

To avoid explicit type templates to deduce the rest, the other solution would be to re-arrange the template like so:
Code:
[NO-PARSE]template <class F, class T, class DelimT = std::string>[/NO-PARSE]

Along with the rest of the type-deduction functions, then the default type chosen for the delimiter will be decided by the class declaration, enabling you to get away with something like:
Code:
[NO-PARSE]template <class F, class T>
predicate_iterator<F, T> create_predicate_iterator(F f, std::basic_ostream<T> &obj)
{
  return predicate_iterator<F, T>(f, obj);
}[/NO-PARSE]
 
Last edited:

Has Sysnative Forums helped you? Please consider donating to help us support the site!

Back
Top