[v3] Add missing forward_list<>::splice_after and merge overloads fix splice_after taking a range

Paolo Carlini paolo.carlini@oracle.com
Fri Apr 13 01:33:00 GMT 2012


Hi,

and thanks for the quick feedback.

On 04/12/2012 11:20 PM, François Dumont wrote:
> One thing after the other :-)
>
> Here is a patch to fix this issue Paolo. The safe iterator 
> _M_valid_range method was considering that a range with different 
> iterators and last being a begin one is invalid which is wrong when 
> there is a before_begin.
>
> 2012-04-12  François Dumont <fdumont@gcc.gnu.org>
>
>     * include/debug/safe_iterator.h (_BeforeBeginHelper<>::__value): Add.
>     (_Safe_Iterator<>::_M_is_beginnest()): Add.
>     * include/debug/safe_iterator.tcc
>     (_Safe_Iterator<>::_M_valid_range): Use latter.
>     * include/debug/forward_list (_BeforeBeginHelper<>::__value): Add.
>     * testsuite/23_containers/forward_list/debug/splice_after.cc:
>     Add check.
>
> Tested in 4.7 branch linux x86_64.
>
> I did this patch in the 4.7 branch because I only had this one ready 
> and moreover I think it should be integrated in it.
Definitely should.

First, I didn't realize so far that we really have a special case here, 
that is only the pair before_begin, begin currently gives problems (I 
suppose you double checked already that other sorts of empty ranges are 
fine).

Then, in terms of implementation details, something like what I'm 
attaching looks a bit more clear to me. What do you think?

Paolo.

///////////////////////
-------------- next part --------------
Index: forward_list
===================================================================
--- forward_list	(revision 186398)
+++ forward_list	(working copy)
@@ -760,8 +760,12 @@
       typedef typename _It::iterator_type _BaseIt;
 
       static bool
-      _M_Is(_BaseIt __it, const _Sequence* __seq)
+      _S_Is(_BaseIt __it, const _Sequence* __seq)
       { return __it == __seq->_M_base().cbefore_begin(); }
+
+      static bool
+      _S_Is_Beginnest(_BaseIt __it, const _Sequence* __seq)
+      { return _S_Is(__it, __seq); }
     };
 }
 
Index: safe_iterator.tcc
===================================================================
--- safe_iterator.tcc	(revision 186398)
+++ safe_iterator.tcc	(working copy)
@@ -1,6 +1,6 @@
 // Debugging iterator implementation (out of line) -*- C++ -*-
 
-// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011
+// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011, 2012
 // Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -91,10 +91,11 @@
 	/* We can only test for equality, but check if one of the
 	   iterators is at an extreme. */
 	/* Optim for classic [begin, it) or [it, end) ranges, limit checks
-	 * when code is valid. */
-	if (_M_is_begin() || __rhs._M_is_end())
+	 * when code is valid.  Note, for the special case of forward_list,
+	 * before_begin replaces the role of begin.  */ 
+	if (_M_is_beginnest() || __rhs._M_is_end())
 	  return true;
-	if (_M_is_end() || __rhs._M_is_begin())
+	if (_M_is_end() || __rhs._M_is_beginnest())
 	  return false;
 
 	// Assume that this is a valid range; we can't check anything else
Index: safe_iterator.h
===================================================================
--- safe_iterator.h	(revision 186398)
+++ safe_iterator.h	(working copy)
@@ -50,8 +50,12 @@
       typedef typename _It::iterator_type _BaseIt;
 
       static bool
-      _M_Is(_BaseIt __it, const _Sequence* __seq)
+      _S_Is(_BaseIt, const _Sequence*)
       { return false; }
+
+      static bool
+      _S_Is_Beginnest(_BaseIt __it, const _Sequence* __seq)
+      { return __it == __seq->_M_base().begin(); }
     };
 
   /** Iterators that derive from _Safe_iterator_base but that aren't
@@ -465,8 +469,16 @@
       /// any?
       bool _M_is_before_begin() const
       {
-	return _BeforeBeginHelper<_Sequence>::_M_Is(base(), _M_get_sequence());
+	return _BeforeBeginHelper<_Sequence>::_S_Is(base(), _M_get_sequence());
       }
+
+      /// Is this iterator equal to the sequence's before_begin() iterator if
+      /// any or begin() otherwise?
+      bool _M_is_beginnest() const
+      {
+	return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(base(),
+							  _M_get_sequence());
+      }
     };
 
   template<typename _IteratorL, typename _IteratorR, typename _Sequence>


More information about the Libstdc++ mailing list