title: Implementing Iterator pattern as a standard conforming class with a reference to a Container in C++
body: <p>I'm trying to implement the iterator pattern, as done in the standard library containers, ie creating a separate <code>Iterator</code> class and not simply by using a typedef, like <code>using iterator = T*;</code>. I want to understand the connection between containers and iterators in the standard library. I have written the following program which resembles an <code>std::array</code> structure and has a nested Iterator class inside. I'm following to the best of my ability the named requirements of the LegacyRandomAccessIterator from <a href="https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator" rel="nofollow noreferrer">cppreference</a>.</p>
  
  <p>I also want to enable range-based-for loop feature for the container, which is why I'm implementing the <code>begin</code> and <code>end</code> methods. They are returning an <code>Iterator</code> now and not simply <code>T*</code>.</p>
  
  <pre><code>#include &lt;algorithm&gt;
  #include &lt;chrono&gt;
  #include &lt;iostream&gt;
  #include &lt;memory&gt;
  #include &lt;random&gt;
  
  template&lt;typename T, typename = std::enable_if_t&lt;std::is_integral_v&lt;T&gt;&gt;&gt;
  class MyArray
  {
      std::size_t m_size;
      std::size_t m_capacity;
      std::unique_ptr&lt;T[]&gt; m_data;
  public:
      using value_type = T;
      using size_type = std::size_t;
      using pointer = T*;
      using const_pointer = T* const;
      using void_pointer = void*;
      using const_void_pointer = void* const;
      using difference_type = std::ptrdiff_t;
      using reference = T&amp;;
      using const_reference = const T&amp;;
  
      constexpr MyArray(std::size_t capacity)
          : m_size{0},
          m_capacity{capacity},
          m_data{std::make_unique&lt;T[]&gt;(capacity)}
      {
          std::size_t m_seed = std::chrono::steady_clock::now().time_since_epoch().count();
          std::default_random_engine m_reng{m_seed};
          // fill up the array with random data
          for (std::size_t i = 0; i &lt; m_size; ++i)
              m_data[i] = m_reng();
      }
  
      class Iterator
      {
          MyArray* v_;
          std::size_t m_index;
      public:
          using iterator_category = typename std::random_access_iterator_tag;
          using value_type = MyArray::value_type;
          using pointer = MyArray::pointer;
          using difference_type = MyArray::difference_type;
          using reference = MyArray::reference;
  
          Iterator(MyArray* v_, std::size_t index)
              : v_{ v_ },
              m_index{ index }
          {}
  
          //operator std::size_t() noexcept {
          //  return m_index;
          //}
  
          T&amp; operator*() {
              return (*v_)[m_index];
          }
          const T&amp; operator*() const {
              return (*v_)[m_index];
          }
          T* operator-&gt;() {
              return &amp;((*v_)[m_index]);
          }
          const T* operator-&gt;() const {
              return &amp;((*v_)[m_index]);
          }
          T&amp; operator[](difference_type m) {
              return (*v_)[m_index + m];
          }
          const T&amp; operator[](difference_type m) const {
              return (*v_)[m_index + m];
          }
  
          /// \brief pre-inc/dec
          Iterator&amp; operator++() noexcept {
              ++m_index;
              return *this;
          }
          Iterator&amp; operator--() noexcept {
              --m_index;
              return *this;
          }
          /// \brief post-inc/dec
          Iterator operator++(int) {
              Iterator r{ *this };
              ++m_index;
              return r;
          }
          Iterator operator--(int) {
              Iterator r{ *this };
              --m_index;
              return r;
          }
  
          Iterator&amp; operator+=(difference_type n) noexcept {
              m_index += n;
              return *this;
          }
          Iterator&amp; operator-=(difference_type n) noexcept {
              m_index -= n;
              return *this;
          }
  
          Iterator operator+(difference_type n) const {
              Iterator r{ *this };
              return r += n;
          }
          Iterator operator-(difference_type n) const {
              Iterator r{ *this };
              return r -= n;
          }
  
          difference_type operator-(Iterator const&amp; r) const noexcept {
              return m_index - r.m_index;
          }
  
          /// \brief comparisons
          inline constexpr bool operator&lt;(const Iterator&amp; it)  const noexcept { return m_index &lt; it.m_index; }
          inline constexpr bool operator&lt;=(const Iterator&amp; it) const noexcept { return m_index &lt;= it.m_index; }
          inline constexpr bool operator&gt;(const Iterator&amp; it)  const noexcept { return m_index &gt; it.m_index; }
          inline constexpr bool operator&gt;=(const Iterator&amp; it) const noexcept { return m_index &gt;= it.m_index; }
          inline constexpr bool operator!=(const Iterator&amp; it) const noexcept { return m_index != it.m_index; }
          inline constexpr bool operator==(const Iterator&amp; it) const noexcept { return m_index == it.m_index; }
      };
  
      using iterator      = Iterator;
      using citerator     = const iterator;
  
      iterator begin() noexcept {
          std::cout &lt;&lt; __func__ &lt;&lt; '\n';
          return &amp;m_data[0];
      }
      iterator end() noexcept {
          std::cout &lt;&lt; __func__ &lt;&lt; '\n';
          return &amp;m_data[m_size - 1];
      }
      const iterator cbegin() const noexcept {
          std::cout &lt;&lt; __func__ &lt;&lt; '\n';
          return &amp;m_data[0];
      }
      const iterator cend() const noexcept {
          std::cout &lt;&lt; __func__ &lt;&lt; '\n';
          return &amp;m_data[m_size - 1];
      }
      T operator[](const std::size_t index) const noexcept {
          std::cout &lt;&lt; __func__ &lt;&lt; '\n';
          return m_data[index];
      }
  };
  </code></pre>
  
  <p>main.cpp for tests:</p>
  
  <pre><code>int main()
  {
      MyArray&lt;int&gt; v{20};
      for (auto it : v) {
          std::cout &lt;&lt; it &lt;&lt; ' ';
      }
      std::cout &lt;&lt; '\n';
      for (const auto cit : v) {
          std::cout &lt;&lt; cit &lt;&lt; ' ';
      }
      std::cout &lt;&lt; '\n';
      for (auto&amp; itr : v) {
          std::cout &lt;&lt; itr &lt;&lt; ' ';
      }
      std::cout &lt;&lt; '\n';
      for (const auto&amp; citr : v) {
          std::cout &lt;&lt; citr &lt;&lt; ' ';
      }
  
      std::cout &lt;&lt; "\nfor_each" &lt;&lt; '\n';
      std::for_each(v.begin(), v.end(), [](int arg)
          {
              std::cout &lt;&lt; arg &lt;&lt; ' ';
          }
      );
  
      std::cout &lt;&lt; "\n\n";
      std::cout &lt;&lt; v[2] &lt;&lt; '\n';
      std::cout &lt;&lt; v[5] &lt;&lt; '\n';
      std::cout &lt;&lt; v[8] &lt;&lt; '\n';
  
      return 0;
  }
  </code></pre>
  
  <p>The error I'm getting is:</p>
  
  <pre><code>error C2440: 'return': cannot convert from 'T' to 'T &amp;'
  with
  [
      T=int
  ]
  note: while compiling class template member function 'T &amp;MyArray&lt;T,void&gt;::Iterator::operator *(void)'
  </code></pre>
  
  <p>which points here in this function the Iterator class:</p>
  
  <pre><code>T&amp; operator*() {
      return (*v_)[m_index];
  }
  </code></pre>
  
  <p>If we follow the named requirements page on cppreference we will find ourselves into <a href="https://en.cppreference.com/w/cpp/named_req/InputIterator" rel="nofollow noreferrer">LegacyInputIterator</a> which implements the <code>*i</code> dereference operation which says that the return value should be <code>reference, convertible to value_type</code>.</p>
  
  <p>The program works if I replace <code>Iterator</code> with <code>T*</code>, but my goal is to implement the iterator and really see how these two concepts (containers and iterators) work together in the standard library. Thus I am missing something with the iterator implementation and I can't find out what it is.</p>