This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Refactor forward_list


Greetings,

In forward_list factored out some routines that construct sequences of nodes.

Added some template technology to prevent (int, int, *) in ctors, insert, and merge from getting sent to (Iter, Iter, *) routines.

Ed Smith-Rowland

Index: /home/ed/gcc/libstdc++-v3/include/bits/forward_list.h
===================================================================
--- /home/ed/gcc/libstdc++-v3/include/bits/forward_list.h	(revision 141181)
+++ /home/ed/gcc/libstdc++-v3/include/bits/forward_list.h	(working copy)
@@ -469,7 +469,9 @@
        *  the default value.
        */
       explicit
-      forward_list(size_type __n);
+      forward_list(size_type __n)
+      : _Base(_Alloc())
+      { _M_fill_initialize(__n, value_type()); }
 
       /**
        *  @brief  Creates a %forward_list with copies of an exemplar element.
@@ -481,7 +483,9 @@
        *  value.
        */
       forward_list(size_type __n, const _Tp& __value,
-                   const _Alloc& __al = _Alloc());
+                   const _Alloc& __al = _Alloc())
+      : _Base(__al)
+      { _M_fill_initialize(__n, __value); }
 
       /**
        *  @brief  Builds a %forward_list from a range.
@@ -495,7 +499,13 @@
        */
       template<typename _InputIterator>
         forward_list(_InputIterator __first, _InputIterator __last,
-		     const _Alloc& __al = _Alloc());
+                     const _Alloc& __al = _Alloc())
+        : _Base(__al)
+        {
+          // Check whether it's an integral type.  If so, it's not an iterator.
+          typedef typename std::__is_integer<_InputIterator>::__type _Integral;
+          _M_initialize_dispatch(__first, __last, _Integral());
+        }
 
       /**
        *  @brief  The %forward_list copy constructor.
@@ -505,7 +515,10 @@
        *  The newly-created %forward_list uses a copy of the allocation
        *  object used by @a list.
        */
-      forward_list(const forward_list& __list);
+      forward_list(const forward_list& __list)
+      : _Base(__list.get_allocator())
+      { _M_initialize_dispatch(__list.begin(), __list.end(),
+                               __false_type()); }
 
       /**
        *  @brief  The %forward_list move constructor.
@@ -528,7 +541,9 @@
        *  in the initializer_list @a il.  This is linear in il.size().
        */
       forward_list(std::initializer_list<_Tp> __il,
-                   const _Alloc& __al = _Alloc());
+                   const _Alloc& __al = _Alloc())
+      : _Base(__al)
+      { _M_initialize_dispatch(__il.begin(), __il.end(), __false_type()); }
 
       /**
        *  @brief  The forward_list dtor.
@@ -871,7 +886,11 @@
        *  does not invalidate iterators and references.
        */
       void
-      insert_after(const_iterator __pos, size_type __n, const _Tp& __val);
+      insert_after(const_iterator __pos, size_type __n, const _Tp& __val)
+      {
+        forward_list<_Tp, _Alloc> __tmp(__n, __val, this->get_allocator());
+        this->splice_after(__pos, std::move(__tmp));
+      }
 
       /**
        *  @brief  Inserts a range into the %forward_list.
@@ -889,7 +908,11 @@
       template<typename _InputIterator>
         void
         insert_after(const_iterator __pos,
-                     _InputIterator __first, _InputIterator __last);
+                     _InputIterator __first, _InputIterator __last)
+        {
+          forward_list<_Tp, _Alloc> __tmp(__first, __last, this->get_allocator());
+          this->splice_after(__pos, std::move(__tmp));
+        }
 
       /**
        *  @brief  Inserts the contents of an initializer_list into
@@ -905,7 +928,11 @@
        *  does not invalidate iterators and references.
        */
       void
-      insert_after(const_iterator __pos, std::initializer_list<_Tp> __il);
+      insert_after(const_iterator __pos, std::initializer_list<_Tp> __il)
+      {
+        forward_list<_Tp, _Alloc> __tmp(__il, this->get_allocator());
+        this->splice_after(__pos, std::move(__tmp));
+      }
 
       /**
        *  @brief  Removes the element pointed to by the iterator following
@@ -1106,7 +1133,8 @@
        *  the pointer is the user's responsibility.
        */
       void
-      unique();
+      unique()
+      { this->unique(std::equal_to<_Tp>()); }
 
       /**
        *  @brief  Remove consecutive elements satisfying a predicate.
@@ -1186,6 +1214,23 @@
        */
       void
       reverse();
+
+    private:
+      template<typename _Integer>
+	void
+	_M_initialize_dispatch(_Integer __n, _Integer __x, __true_type)
+	{ _M_fill_initialize(static_cast<size_type>(__n), __x); }
+
+      // Called by the range constructor to implement [23.1.1]/9
+      template<typename _InputIterator>
+	void
+	_M_initialize_dispatch(_InputIterator __first, _InputIterator __last,
+			       __false_type);
+
+      // Called by forward_list(n,v,a), and the range constructor when it turns out
+      // to be the same thing.
+      void
+      _M_fill_initialize(size_type __n, const value_type& __value);
     };
 
   /**
Index: /home/ed/gcc/libstdc++-v3/include/bits/forward_list.tcc
===================================================================
--- /home/ed/gcc/libstdc++-v3/include/bits/forward_list.tcc	(revision 141181)
+++ /home/ed/gcc/libstdc++-v3/include/bits/forward_list.tcc	(working copy)
@@ -206,38 +206,13 @@
       return __pos;
     }
   
+  // Called by the range constructor to implement [23.1.1]/9
   template<typename _Tp, typename _Alloc>
-    forward_list<_Tp, _Alloc>::
-    forward_list(size_type __n)
-    : _Base()
-    {
-      _Fwd_list_node_base* __to = &this->_M_impl._M_head;
-      for (size_type __i = 0; __i < __n; ++__i)
-	{
-	  __to->_M_next = this->_M_create_node(_Tp());
-	  __to = __to->_M_next;
-	}
-    }
-
-  template<typename _Tp, typename _Alloc>
-    forward_list<_Tp, _Alloc>::
-    forward_list(size_type __n, const _Tp& __value, const _Alloc& __al)
-    : _Base(__al)
-    {
-      _Fwd_list_node_base* __to = &this->_M_impl._M_head;
-      for (size_type __i = 0; __i < __n; ++__i)
-	{
-	  __to->_M_next = this->_M_create_node(__value);
-	  __to = __to->_M_next;
-	}
-    }
-
-  template<typename _Tp, typename _Alloc>
     template<typename _InputIterator>
+      void
       forward_list<_Tp, _Alloc>::
-      forward_list(_InputIterator __first, _InputIterator __last,
-                   const _Alloc& __al)
-      : _Base(__al)
+      _M_initialize_dispatch(_InputIterator __first, _InputIterator __last,
+                             __false_type)
       {
         _Fwd_list_node_base* __to = &this->_M_impl._M_head;
         _InputIterator __curr = __first;
@@ -249,37 +224,22 @@
           }
       }
 
+  // Called by forward_list(n,v,a), and the range constructor
+  // when it turns out to be the same thing.
   template<typename _Tp, typename _Alloc>
+    void
     forward_list<_Tp, _Alloc>::
-    forward_list(const forward_list& __list)
-    : _Base(__list._M_get_Node_allocator())
+    _M_fill_initialize(size_type __n, const value_type& __value)
     {
-      const _Fwd_list_node_base* __from = &__list._M_impl._M_head;
       _Fwd_list_node_base* __to = &this->_M_impl._M_head;
-      while (__from->_M_next != 0)
-	{
-	  const _Node* __temp = static_cast<_Node*>(__from->_M_next);
-	  __to->_M_next = this->_M_create_node(__temp->_M_value);
-	  __from = __from->_M_next;
-	  __to = __to->_M_next;
-	}
+      for (; __n > 0; --__n)
+        {
+          __to->_M_next = this->_M_create_node(__value);
+          __to = __to->_M_next;
+        }
     }
 
   template<typename _Tp, typename _Alloc>
-    forward_list<_Tp, _Alloc>::
-    forward_list(std::initializer_list<_Tp> __il, const _Alloc& __al)
-    : _Base(__al)
-    {
-      _Fwd_list_node_base* __to = &this->_M_impl._M_head;
-      for (const _Tp* __item = __il.begin();
-	   __item != __il.end(); ++__item)
-	{
-	  __to->_M_next = this->_M_create_node(*__item);
-	  __to = __to->_M_next;
-	}
-    }
-
-  template<typename _Tp, typename _Alloc>
     forward_list<_Tp, _Alloc>&
     forward_list<_Tp, _Alloc>::
     operator=(const forward_list& __list)
@@ -309,61 +269,6 @@
   template<typename _Tp, typename _Alloc>
     void
     forward_list<_Tp, _Alloc>::
-    insert_after(const_iterator __pos,
-		 size_type __n, const _Tp& __val)
-    {
-      _Fwd_list_node_base* __to
-	= const_cast<_Fwd_list_node_base*>(__pos._M_node);
-      _Fwd_list_node_base* __keep = __to->_M_next;
-      for (size_type __i = 0; __i < __n; ++__i)
-	{
-	  __to->_M_next = this->_M_create_node(__val);
-	  __to = __to->_M_next;
-	}
-      __to->_M_next = __keep;
-    }
-
-  template<typename _Tp, typename _Alloc>
-    template<typename _InputIterator>
-      void
-      forward_list<_Tp, _Alloc>::
-      insert_after(const_iterator __pos,
-		   _InputIterator __first, _InputIterator __last)
-      {
-	_Fwd_list_node_base* __to
-	  = const_cast<_Fwd_list_node_base*>(__pos._M_node);
-	_Fwd_list_node_base* __keep = __to->_M_next;
-	_InputIterator __curr = __first;
-	while (__curr != __last)
-	  {
-	    __to->_M_next = this->_M_create_node(*__curr);
-	    __to = __to->_M_next;
-	    ++__curr;
-	  }
-	__to->_M_next = __keep;
-      }
-
-  template<typename _Tp, typename _Alloc>
-    void
-    forward_list<_Tp, _Alloc>::
-    insert_after(const_iterator __pos, std::initializer_list<_Tp> __il)
-    {
-      _Fwd_list_node_base* __to
-	= const_cast<_Fwd_list_node_base*>(__pos._M_node);
-      _Fwd_list_node_base* __keep = __to->_M_next;
-      const _Tp* __item = __il.begin();
-      while (__item != __il.end())
-	{
-	  __to->_M_next = this->_M_create_node(*__item);
-	  __to = __to->_M_next;
-	  ++__item;
-	}
-      __to->_M_next = __keep;
-    }
-
-  template<typename _Tp, typename _Alloc>
-    void
-    forward_list<_Tp, _Alloc>::
     resize(size_type __sz, value_type __val)
     {
       iterator __k = before_begin();
@@ -441,26 +346,6 @@
       }
 
   template<typename _Tp, typename _Alloc>
-    void
-    forward_list<_Tp, _Alloc>::
-    unique()
-    {
-      iterator __first = begin();
-      iterator __last = end();
-      if (__first == __last)
-	return;
-      iterator __next = __first;
-      while (++__next != __last)
-	{
-	  if (*__first == *__next)
-	    erase_after(__first);
-	  else
-	    __first = __next;
-	  __next = __first;
-	}
-    }
-
-  template<typename _Tp, typename _Alloc>
     template<typename _BinPred>
       void
       forward_list<_Tp, _Alloc>::
Index: /home/ed/gcc/libstdc++-v3/testsuite/23_containers/forward_list/modifiers/2.cc
===================================================================
--- /home/ed/gcc/libstdc++-v3/testsuite/23_containers/forward_list/modifiers/2.cc	(revision 141181)
+++ /home/ed/gcc/libstdc++-v3/testsuite/23_containers/forward_list/modifiers/2.cc	(working copy)
@@ -51,7 +51,7 @@
 
   // Note: Calling l.insert_after(pos, 5, 42); without the long five
   // gets resolved to the iterator range version and fails to compile!
-  fl.insert_after(pos, 5L, 42);
+  fl.insert_after(pos, 5, 42);
   VERIFY(*pos == 1);
 
   ++pos;
Index: /home/ed/gcc/libstdc++-v3/testsuite/23_containers/forward_list/synopsis.cc
===================================================================
--- /home/ed/gcc/libstdc++-v3/testsuite/23_containers/forward_list/synopsis.cc	(revision 0)
+++ /home/ed/gcc/libstdc++-v3/testsuite/23_containers/forward_list/synopsis.cc	(revision 0)
@@ -0,0 +1,53 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+#include <forward_list>
+
+namespace std {
+  template <class T, class Allocator> class forward_list;
+
+  template <class T, class Allocator>
+  bool operator==(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>&);
+
+  template <class T, class Allocator>
+  bool operator< (const forward_list<T,Allocator>& x, const forward_list<T,Allocator>&);
+
+  template <class T, class Allocator>
+    bool operator!=(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>&);
+
+  template <class T, class Allocator>
+    bool operator> (const forward_list<T,Allocator>& x, const forward_list<T,Allocator>&);
+
+  template <class T, class Allocator>
+    bool operator>=(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>&);
+
+  template <class T, class Allocator>
+    bool operator<=(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>&);
+
+  template <class T, class Allocator>
+    void swap(forward_list<T,Allocator>& x, forward_list<T,Allocator>& y);
+
+  template <class T, class Allocator>
+    void swap(forward_list<T,Allocator>&& x, forward_list<T,Allocator>& y);
+
+  template <class T, class Allocator>
+    void swap(forward_list<T,Allocator>& x, forward_list<T,Allocator>&& y);
+}

Attachment: CL_forward_list
Description: video/flv


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]