/* Voorbeeldcode behorende bij het college "Programmeertechnieken",
 * LIACS, Universiteit Leiden.
 */

#include <iostream>
#include <vector>
#include <iterator>

/* Forward declaration */
class MijnIterator;

class MijnContainer
{
  private:
    std::vector<int> members;

  public:
    /* Note: C++-11 style initialization */
    MijnContainer(void)
      : members{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }
    { }

    int &getValue(const size_t offset)
    {
      return members[offset];
    }

    /* Het is conventie om een typedef naar het type iterator voor deze
     * klasse toe te voegen aan de klasse. Je kunt dan schrijven
     * MijnContainer::iterator, vergelijk met de STL containers.
     */
    typedef MijnIterator iterator;

    MijnIterator begin(void);
    MijnIterator end(void);
};

class MijnIterator : public std::iterator<std::input_iterator_tag, int>
{
  private:
    MijnContainer &container;
    size_t offset;

  public:
    MijnIterator(MijnContainer &container, size_t offset)
      : container(container), offset(offset)
    { }

    bool operator==(const MijnIterator &iter) const
    {
      return &iter.container == &container && iter.offset == offset;
    }

    bool operator!=(const MijnIterator &iter) const
    {
      return !operator==(iter);
    }

    int &operator*() const
    {
      return container.getValue(offset);
    }

    int *operator->() const
    {
      return &container.getValue(offset);
    }

    MijnIterator &operator++()
    {
      ++offset;
      return *this;
    }
};

/* Implementatie methoden uit MijnContainer */
MijnIterator MijnContainer::begin(void)
{
  return MijnIterator(*this, 0);
}

MijnIterator MijnContainer::end(void)
{
  return MijnIterator(*this, members.size());
}


int main (void)
{
  MijnContainer container;

  /* Klassiek C++ iteration */
  for (MijnContainer::iterator it = container.begin();
       it != container.end(); ++it)
    std::cout << *it << " ";
  std::cout << std::endl;

  /* C++-11 style iteration. Mogelijk omdat MijnContainer begin() en end() 
   * methoden heeft.
   */
  for (auto member : container)
    std::cout << member << " ";
  std::cout << std::endl;

  return 0;
}