C++ iterator wrapper/adaptor example
May 12, 2017 [C++, Tech]Series: Iterator, Iterator Wrapper, Non-1-1 Wrapper
If you want to wrap an iterable range with another that transforms the underlying iterators in some way and allows looping or constructing other objects:
for (auto ch : Upper("abcdef"))
{
// Prints "ABCDEF"
std::cout << ch;
}
Upper up(std::string("fOo"));
std::string newfoo(std::begin(up), std::end(up));
assert(newfoo == "FOO");
then, similar to an ordinary iterable range you will need to make a range class and a iterator class:
class myit
{
private:
std::string::const_iterator wrapped_;
class charholder
{
const char value_;
public:
charholder(const char value) : value_(value) {}
char operator*() const { return value_; }
};
public:
// Previously provided by std::iterator
typedef int value_type;
typedef std::ptrdiff_t difference_type;
typedef int* pointer;
typedef int& reference;
typedef std::input_iterator_tag iterator_category;
explicit myit(std::string::const_iterator wrapped) : wrapped_(wrapped) {}
value_type operator*() const { return std::toupper(*wrapped_); }
bool operator==(const myit& other) const { return wrapped_ == other.wrapped_; }
bool operator!=(const myit& other) const { return !(*this == other); }
charholder operator++(int)
{
charholder ret(std::toupper(*wrapped_));
++wrapped_;
return ret;
}
myit& operator++()
{
++wrapped_;
return *this;
}
};
class Upper
{
private:
const std::string str_;
public:
Upper(const std::string str) : str_(str) {}
myit begin() { return myit(std::begin(str_)); }
myit end() { return myit(std::end(str_)); }
};
Notice the need to call the transforming/adapting functionstd::toupper in two places.
Update: std::iterator is deprecated in C++17, so removed.