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]

[RFC/Patch] libstdc++/23767


Hi everyone, hi Gaby,

I'm trying to figure the "best" fix for this annoying issue, due
basically to the templatized constructor of our __normal_iterator, which
gives us problems when an overload set including both iterator and
const_iterator is constructed (see attached testcase).

Chris proposed in the audit trail a sophisticated solution using
enable_if and is_convertible, which is general and avoids code
duplication, but, well, brings in the usual trickeries (an additional
dummy argument, is_convertible should be uglified in order to be used, etc.)

An alternate solution, much more simple which I'm currently exploring
(regtesting and testcase coming with 23767 are both OK) is the attached,
which consists only of two specializations for const Tp* and Tp* (the
cases that really matter in our library) for the first template argument
of __normal_iterator. This one too should be safe from the point of view
of the binary compatibility.

What do you think? 1), 2) or... 3) ??

Paolo.

////////////////////
#include <vector>

struct T {
  typedef std::vector<int> Vector;
  typedef Vector::iterator iterator;
  typedef Vector::const_iterator const_iterator;

  int t( iterator f)             { return *f; }
  int t( const_iterator f) const { return *f; }
};

int main(int, char*[])
{
  std::vector<int> v(1, 1);
  T t;
  T::const_iterator i = v.begin();

  t.t(i);

  return 0;

}
Index: stl_iterator.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/stl_iterator.h,v
retrieving revision 1.28
diff -u -r1.28 stl_iterator.h
--- stl_iterator.h	17 Aug 2005 02:13:00 -0000	1.28
+++ stl_iterator.h	11 Sep 2005 15:02:14 -0000
@@ -666,6 +666,174 @@
       { return _M_current; }
     };
 
+  template<typename _Tp, typename _Container>
+    class __normal_iterator<_Tp*, _Container>
+    {
+    protected:
+      typedef _Tp* _Iterator;
+      _Iterator _M_current;
+
+    public:
+      typedef typename iterator_traits<_Iterator>::iterator_category
+                                                             iterator_category;
+      typedef typename iterator_traits<_Iterator>::value_type  value_type;
+      typedef typename iterator_traits<_Iterator>::difference_type
+                                                             difference_type;
+      typedef typename iterator_traits<_Iterator>::reference reference;
+      typedef typename iterator_traits<_Iterator>::pointer   pointer;
+
+      __normal_iterator() : _M_current(_Iterator()) { }
+
+      explicit
+      __normal_iterator(const _Iterator& __i) : _M_current(__i) { }
+
+      __normal_iterator(const __normal_iterator& __i)
+      : _M_current(__i.base()) { }
+
+      // Forward iterator requirements
+      reference
+      operator*() const
+      { return *_M_current; }
+
+      pointer
+      operator->() const
+      { return _M_current; }
+
+      __normal_iterator&
+      operator++()
+      {
+	++_M_current;
+	return *this;
+      }
+
+      __normal_iterator
+      operator++(int)
+      { return __normal_iterator(_M_current++); }
+
+      // Bidirectional iterator requirements
+      __normal_iterator&
+      operator--()
+      {
+	--_M_current;
+	return *this;
+      }
+
+      __normal_iterator
+      operator--(int)
+      { return __normal_iterator(_M_current--); }
+
+      // Random access iterator requirements
+      reference
+      operator[](const difference_type& __n) const
+      { return _M_current[__n]; }
+
+      __normal_iterator&
+      operator+=(const difference_type& __n)
+      { _M_current += __n; return *this; }
+
+      __normal_iterator
+      operator+(const difference_type& __n) const
+      { return __normal_iterator(_M_current + __n); }
+
+      __normal_iterator&
+      operator-=(const difference_type& __n)
+      { _M_current -= __n; return *this; }
+
+      __normal_iterator
+      operator-(const difference_type& __n) const
+      { return __normal_iterator(_M_current - __n); }
+
+      const _Iterator&
+      base() const
+      { return _M_current; }
+    };
+
+  template<typename _Tp, typename _Container>
+    class __normal_iterator<const _Tp*, _Container>
+    {
+    protected:
+      typedef const _Tp* _Iterator;
+      _Iterator _M_current;
+
+    public:
+      typedef typename iterator_traits<_Iterator>::iterator_category
+                                                             iterator_category;
+      typedef typename iterator_traits<_Iterator>::value_type  value_type;
+      typedef typename iterator_traits<_Iterator>::difference_type
+                                                             difference_type;
+      typedef typename iterator_traits<_Iterator>::reference reference;
+      typedef typename iterator_traits<_Iterator>::pointer   pointer;
+
+      __normal_iterator() : _M_current(_Iterator()) { }
+
+      explicit
+      __normal_iterator(const _Iterator& __i) : _M_current(__i) { }
+
+      __normal_iterator(const __normal_iterator& __i)
+      : _M_current(__i.base()) { }
+
+      // Allow _Tp* to const _Tp* conversion
+      __normal_iterator(const __normal_iterator<_Tp*, _Container>& __i)
+      : _M_current(__i.base()) { }
+
+      // Forward iterator requirements
+      reference
+      operator*() const
+      { return *_M_current; }
+
+      pointer
+      operator->() const
+      { return _M_current; }
+
+      __normal_iterator&
+      operator++()
+      {
+	++_M_current;
+	return *this;
+      }
+
+      __normal_iterator
+      operator++(int)
+      { return __normal_iterator(_M_current++); }
+
+      // Bidirectional iterator requirements
+      __normal_iterator&
+      operator--()
+      {
+	--_M_current;
+	return *this;
+      }
+
+      __normal_iterator
+      operator--(int)
+      { return __normal_iterator(_M_current--); }
+
+      // Random access iterator requirements
+      reference
+      operator[](const difference_type& __n) const
+      { return _M_current[__n]; }
+
+      __normal_iterator&
+      operator+=(const difference_type& __n)
+      { _M_current += __n; return *this; }
+
+      __normal_iterator
+      operator+(const difference_type& __n) const
+      { return __normal_iterator(_M_current + __n); }
+
+      __normal_iterator&
+      operator-=(const difference_type& __n)
+      { _M_current -= __n; return *this; }
+
+      __normal_iterator
+      operator-(const difference_type& __n) const
+      { return __normal_iterator(_M_current - __n); }
+
+      const _Iterator&
+      base() const
+      { return _M_current; }
+    };
+
   // Note: In what follows, the left- and right-hand-side iterators are
   // allowed to vary in types (conceptually in cv-qualification) so that
   // comparaison between cv-qualified and non-cv-qualified iterators be

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