-- Leo's gemini proxy

-- Connecting to republic.circumlunar.space:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini

C++ iterator example (and an iterable range)


Series: Iterator, Iterator Wrapper, Non-1-1 Wrapper


To make your own iterable range in C++ that you can loop over or make a vector out of (mine is called Numbers):


Iterator Wrapper

Non-1-1 Wrapper


// Prints:
// 3,4,
for (auto n : Numbers(3, 5))
{
   std::cout << n << ",";
}

// Fills vec with 7, 8, 9
Numbers nums(7, 10);
std::vector vec{std::begin(nums), std::end(nums)};


you need to write a class that is an Input Iterator, and provide an instance as the begin and end of your range:


class Numbers
{
private:
   const int start_;
   const int end_;
public:
   Numbers(int start, int end) : start_(start) , end_(end) {}
   myit begin() { return myit(start_); }
   myit end()   { return myit(end_); }
};


The hard bit is the Input Iterator:


#include <iterator>

class myit
{
private:
   int value_;
   class intholder
   {
       int value_;
   public:
       intholder(int value): value_(value) {}
       int operator*() { return value_; }
   };
public:
   // Previously provided by std::iterator - see update below
   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(int value) : value_(value) {}
   int operator*() const { return value_; }
   bool operator==(const myit& other) const { return value_ == other.value_; }
   bool operator!=(const myit& other) const { return !(*this == other); }
   intholder operator++(int)
   {
       intholder ret(value_);
       ++*this;
       return ret;
   }
   myit& operator++()
   {
       ++value_;
       return *this;
   }
};


Update : thanks to Anthony Williams for the correction on the postincrement operator - see Generating Sequences for more. Note the need to return a fiddly object that holds the answer we will give when the return value is dereferenced.


Generating Sequences


Using std::iterator as a base class actually only gives you some typedefs for free, but it's worth it to get the standard names, and to be clear what we are trying to do. Update: std::iterator is deprecated in C++17 - just add the 5 typedefs yourself.


I suspect I might need to add some extra &s to make this good C++11 style?


Originally posted at 2017-05-11 06:15:28+00:00. Automatically generated from the original post : apologies for the errors introduced.


std::iterator is deprecated in C++17

original post

-- Response ended

-- Page fetched on Mon May 27 20:26:28 2024