title: Generic doubly linked list copy constructor efficiency and linkage
body: <p>I am having an issue with implementing the following two <em>constructors</em>:</p>
  <pre><code>List(const List&amp; other)
  ~List()
  </code></pre>
  <p>Originally, the copy constructor was written as:</p>
  <pre><code>for (auto current = other._head._next; current != &amp;other._head; current = current-&gt;_prev){
              push_back(static_cast&lt;T*&gt;(current));
          }
  </code></pre>
  <p>The above is considered <strong>ineffective</strong> and <strong>inefficient</strong>. So, I am trying to re-write it like this:</p>
  <pre><code>for (auto ptr = other._head._next; ptr != &amp;other._head; ptr = ptr-&gt;_next)
          {
              T* item = new T(*dynamic_cast&lt;T*&gt;(ptr)));
  
              Link&lt;T&gt;* current = &amp;_head;
              Link&lt;T&gt;* previous = &amp;_head;
  
              current-&gt;_next = item;
              previous = current;
  
              /*
              
              // link to new head
              _head._next = other._head._next;
              _head._prev = other._head._prev;
  
              // Link prev och next to correct head
              _head._next-&gt;_prev = &amp;_head;
              _head._prev-&gt;_next = &amp;_head;
              
              */
          }
  </code></pre>
  <p>However, I am a total newbie on understanding how this Next, Prev, Next Prev, and finally connect together has to be done properly in the context of this copy constructor and the destructor. So, I am not sure why the above does not work and I am asking if someone know this and can help out here.</p>
  <p><strong>Link.hpp</strong></p>
  <pre><code>template&lt;class T&gt;
  class Link {
      template&lt;class&gt; friend class List;
      Link* _next, * _prev;
  public:
      Link() : _next(this), _prev(this) {}
      virtual ~Link() {}
      T* next() const { return dynamic_cast&lt;T*&gt;(_next); }
      T* prev() const { return dynamic_cast&lt;T*&gt;(_prev); }
  
      T* insert_after(T* in)
      {
          in-&gt;_next = this;
          in-&gt;_prev = m_prev;
          _prev-&gt;_next = in;
          _prev = in;
          return in;
      }
  
      T* insert_before(T* in)
      {
          return _prev-&gt;insert_after(in);
      }
  
      T* remove()
      {
          _prev-&gt;_next = _next;
          _next-&gt;_prev = _prev;
          return dynamic_cast&lt;T*&gt;(this);
      }
  
      void splice_after(Link* f, Link* l)
      {
          if (f != l){
              f-&gt;_prev-&gt;_next = l-&gt;_next;
              last-&gt;_next-&gt;_prev = f-&gt;_prev;
  
              f-&gt;_prev = this;
              l-&gt;_next = this-&gt;_next;
              _next-&gt;_prev = l;
              _next = f;
          }
      }
  
      void splice_before(Link* f, Link* l)
      {
          m_prev-&gt;splice_after(f, l);
      }
  
      T* erase_first()
      {
          Link* tmp = _next;
          _next = _next-&gt;_next;
          _next-&gt;_prev = this;
          return static_cast&lt;T*&gt;(tmp);
      }
  
      T* erase_last() {
          Link* tmp = _prev;
          _prev = _prev-&gt;_prev;
          _prev-&gt;_next = this;
          return static_cast&lt;T*&gt;(tmp);
      }
  };
  </code></pre>
  <p><strong>List.hpp:</strong></p>
  <pre><code>#include &lt;string.h&gt;
  
  template&lt;class T&gt; 
  class List {
      template&lt;class X&gt; class ListIter {
          template&lt;class&gt; friend class List;
          Link&lt;T&gt;* _ptr;
      public:
          // Typedefs
          typedef std::bidirectional_iterator_tag iterator_category;
          typedef ptrdiff_t difference_type;
          typedef std::remove_const_t&lt;X&gt;  value_type;
          typedef X* pointer;
          typedef X&amp; reference;
      public:
          ListIter() : _ptr{ nullptr } {}
          ListIter(Link&lt;T&gt;* ptr) : _ptr{ ptr } {}
          ListIter(const ListIter&amp; other) : _ptr{other._ptr} {}
          ListIter&amp; operator=(const ListIter&amp; other) 
          {
              _ptr = other._ptr;
              return *this;
          }
  
          X&amp; operator*() { return *dynamic_cast&lt;T*&gt;(_ptr); }
          X* operator-&gt;() { return dynamic_cast&lt;T*&gt;(_ptr); }
          ListIter&amp; operator++() { _ptr = static_cast&lt;T*&gt;(_ptr-&gt;_next); return *this; }
          ListIter&amp; operator--(){ _ptr = static_cast&lt;T*&gt;(_ptr-&gt;_prev); return *this; }
          ListIter operator++(int) { auto r(*this); operator++(); return r; }
          ListIter operator--(int){ auto r(*this); operator--(); return r; }
          difference_type operator-(const ListIter&amp; other) {
              return (_ptr - other._ptr);
          }
  
          friend auto operator&lt;=&gt;(const ListIter&amp; lhs, const ListIter&amp; rhs)
          {
              if ((lhs._ptr - rhs._ptr) &lt; 0)
                  return std::strong_ordering::less;
              else if ((lhs._ptr - rhs._ptr) &gt; 0)
                  return std::strong_ordering::greater;
              return std::strong_ordering::equivalent;
          }
  
          friend bool operator==(const ListIter&amp; lhs, const ListIter&amp; rhs)
          {
              return (lhs &lt;=&gt; rhs) == 0;
          }
      };
  
      Link&lt;T&gt; _head;
  
  public:
      using iterator = ListIter&lt;T&gt;;
      using const_iterator = ListIter&lt;const T&gt;;
  
      List() 
      {
          _head._next = &amp;_head;
          _head._prev = &amp;_head;
      }
      
      List(const List&amp; other) // Problem here, does not work, not sure how to get this solved.
      {
  for (auto ptr = other._head._next; ptr != &amp;other._head; ptr = ptr-&gt;_next)
          {
              T* item = new T(*dynamic_cast&lt;T*&gt;(ptr)));
  
              Link&lt;T&gt;* current = &amp;_head;
              Link&lt;T&gt;* previous = &amp;_head;
  
              current-&gt;_next = item;
              previous = current;
  
              /*
              
              // link to new head
              _head._next = other._head._next;
              _head._prev = other._head._prev;
  
              // Link prev och next to correct head
              _head._next-&gt;_prev = &amp;_head;
              _head._prev-&gt;_next = &amp;_head;
              
              */
      }
      }
      
      List(const char* other)
      {
          for (size_t i = 0; i &lt; strlen(other); ++i)
              _head.insert_after(new T(other[i]));
      }
  
      ~List()
      {
          while (_head._next != &amp;_head)
          {
              pop_front();  // This isn't efficient. 
          }
      }
  
      T* pop_front() 
      {
          return _head.erase_first();
      }
      
      T* pop_back() 
      {
          return _head.erase_last();
      }
  
      void push_front(T* node) { _head.insert_before(node);}
      void push_back(T* node) { _head.insert_after(node);}
  };
  </code></pre>