title: Iterator for a list implemented using unique_ptr
body: <p>I am creating a datastructure that uses <code>unique_ptr</code>. I now want to define different iterators over this datastructure, however the nodes of my data structure are part of the data itself. Because of this I want the iterators to return the actual nodes and not only the values contained within.</p>
  
  <p>Here is what I got so far (much simplified example):</p>
  
  <pre><code>#include &lt;algorithm&gt;
  #include &lt;iostream&gt;
  #include &lt;memory&gt;
  
  using namespace std;
  
  template &lt;typename T&gt; struct node {
    node(T val) : val(val), next(nullptr) {}
    node(T val, unique_ptr&lt;node&lt;T&gt;&gt; &amp;n) : val(val), next(move(n)) {}
    T val;
    unique_ptr&lt;node&lt;T&gt;&gt; next;
  
    template &lt;bool Const = true&gt; struct iter {
      using reference =
          typename std::conditional&lt;Const, const node&lt;T&gt; *, node&lt;T&gt; *&gt;::type;
      iter() : nptr(nullptr) {}
      iter(node&lt;T&gt; *n) : nptr(n) {}
  
      reference operator*() { return nptr; }
  
      iter &amp;operator++() {
        nptr = nptr-&gt;next.get();
        return *this;
      }
  
      friend bool operator==(const iter &amp;lhs, const iter &amp;rhs) {
        return lhs.nptr == rhs.nptr;
      }
  
      friend bool operator!=(const iter &amp;lhs, const iter &amp;rhs) {
        return lhs.nptr != rhs.nptr;
      }
      node&lt;T&gt; *nptr;
    };
  
    iter&lt;&gt; begin() const { return iter&lt;&gt;(this); }
    iter&lt;&gt; end() const { return iter&lt;&gt;(); }
  
    iter&lt;false&gt; begin() { return iter&lt;false&gt;(this); }
    iter&lt;false&gt; end() { return iter&lt;false&gt;(); }
  };
  
  template &lt;typename T&gt; void pretty_print(const unique_ptr&lt;node&lt;T&gt;&gt; &amp;l) {
    auto it = l-&gt;begin();
    while (it != l-&gt;end()) {
      auto elem = *it;
      cout &lt;&lt; elem-&gt;val &lt;&lt; endl;
      ++it;
    }
  }
  
  int main() {
    auto a = make_unique&lt;node&lt;int&gt;&gt;(4);
    auto b = make_unique&lt;node&lt;int&gt;&gt;(3, a);
    auto c = make_unique&lt;node&lt;int&gt;&gt;(2, b);
    auto d = make_unique&lt;node&lt;int&gt;&gt;(1, c);
  
    for (auto *elem : *d) {
      elem-&gt;val = elem-&gt;val - 1;
    }
  
    pretty_print(d);
  
    return 0;
  }
  </code></pre>
  
  <p>Is it considered bad practice to expose the raw pointers to the elements of the datastructure in this way? Will this work in a more complex example, especially in regard to <code>const</code>-correctness?</p>