This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: libstdc++/10783: std::vector::reverse_iterator could be smaller
- From: Sylvain Pion <Sylvain dot Pion at mpi-sb dot mpg dot de>
- To: Paolo Carlini <pcarlini at unitus dot it>, gcc-prs at gcc dot gnu dot org, Sylvain dot Pion at mpi-sb dot mpg dot de, gcc-bugs at gcc dot gnu dot org, gcc-gnats at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
- Date: Thu, 22 May 2003 17:58:18 +0200
- Subject: Re: libstdc++/10783: std::vector::reverse_iterator could be smaller
- References: <3EC7E096.5040103@unitus.it> <20030518224528.GF22583@tofu.dreamhost.com>
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