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]

Re: libstdc++/10783: std::vector::reverse_iterator could be smaller


On Sun, May 18, 2003 at 03:45:28PM -0700, Nathan Myers wrote:
> On Sun, May 18, 2003 at 09:35:50PM +0200, Paolo Carlini wrote:
> > Well, on second thought, and giving justice to the clear
> > explanation in V&J, in their ?16.2.2 it is clearly stated
> > that the EBCO has no equivalent for data members: this is
> > reasonable considering that it would create problems with
> > the representation of pointers to members.
> > 
> > Therefore reverse_iterator is expected to have the same
> > size of its iterator empty base (thanks to EBCO) + the size
> > of its member current, that is two times the size of a
> > plain iterator.
> > 
> > http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=10783
> 
> I agree it would be a Good Thing for the reverse iterators to 
> be the same size as the regular iterators.
> 
> It seems to me that this is one of those cases where the regular
> empty-base optimization can't be applied.  That is, the ABI
> forbids it because two base-class subobjects of the same type
> would have the same type.
> 
> Often you can get around this sort of thing by giving the base an 
> extra, defaulted, dummy argument, and deriving from a variant,
> so the two base subobjects that share the same address have 
> different types.  I think that doesn't work here because the 
> derivation hierarchy and the argument list to std::iterator<> might 
> be fixed by the standard.

This derivation is fixed by the standard, but not the one that
exists in std::vector::iterator.  So there is some room there.

> A tricky way would be to arrange that the addresses of the two base
> subobjects are at opposite ends of the object:
> 
>   struct empty {};
>   struct notempty { int i; };
> 
>   struct iterator : empty { notempty n; };   // sizeof is 4
> 
>   struct riterator_base { iterator i; };  // has empty at offset 0
>   struct riterator // has empty at both offsets 0 and 4.
>     : riterator_base, empty {};   // sizeof should still be 4.
> 
> Unfortunately this doesn't work.  sizeof(riterator) is 8. :-(
> This is probably a result of an unfortunate oversight by the
> ia64 ABI group.

If this worked, and you considered an array of two such riterators, then
you would have the first empty base object of the second riterator, which
would have the same address as the second empty object of the first riterator.
So I don't see this as an oversight.


As far as this PR is concerned, since std::vector::iterator is a
__normal_iterator, and I don't see a reason why it's useful that
__normal_iterator derives from iterator<...>, then I would suggest
to remove this derivation from __normal_iterator, with something
like the following, completely untested patch :

diff -u -r1.22 stl_iterator.h
--- stl_iterator.h      20 Jul 2002 06:26:27 -0000      1.22
+++ stl_iterator.h      22 May 2003 15:51:08 -0000
@@ -569,16 +569,14 @@
   using std::iterator;
   template<typename _Iterator, typename _Container>
     class __normal_iterator
-      : public iterator<typename iterator_traits<_Iterator>::iterator_category,-                        typename iterator_traits<_Iterator>::value_type,
-                        typename iterator_traits<_Iterator>::difference_type,
-                        typename iterator_traits<_Iterator>::pointer,
-                        typename iterator_traits<_Iterator>::reference>
     {
     protected:
       _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;


What do you think ?

-- 
Sylvain


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