Topic: STL: operator-> for iterators
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Mon, 27 Feb 1995 14:38:03 +0000 Raw View
In article <3ikp2f$gv5@castle.york.ac.uk> sp106@york.ac.uk "stephen" writes:
>Nathan Myers (ncm@netcom.com) wrote:
>: >Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
>: >>The STL documentation and source code that I have are from Sept/Oct '95,
>: >>so the problem may have been addressed. Given that iterators in STL have
>: >>pointer like semantics, why is there no operator-> defined for them?
>: >>This came to light recently after I implemented an STL-like container and
>: >>someone came to me saying that they had loads of code like
>: >> (*iter).member()
>: The operator -> is not part of the required interface for iterators
>: because that would place an extra burden on writers of iterators.
>: We can all expect to write hundreds of iterators in our careers, and
>: you would soon resent being obliged to provide such an unnecessary
>: operator.
>
>Surely the point is more simple than this: that given an operator->
>the iterator would unable to work on a container containing simple
>objects. I ran into this when writing my own STL'ish library, a
>iterator for Container<int> _may_ try to instantiate operator-> for
>the iterator which will cause a compile time error. What is the
>thinking on this at the moment, does the instantiation of the
>operator _have_ to occur, and if not does the syntax of the code
>that would be generated if this was the case have to be correct?
>If not then template code of any type is an error waiting to happen.
I don't believe there is a problem w/ this, as you cannot use the operator->
in syntax sugared form with ints, ie. there does not exists an m such that
x->m is valid. As I stated in an earlier post, I presume that the auto_ptr<>
class has operator-> and this should work w/ ints.
+---------------------------+------------------------------------+
| Kevlin A P Henney | Money confers neither intelligence |
| kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
| Westinghouse Systems Ltd | |
+---------------------------+------------------------------------+
Author: rjl@f111.iassf.easams.com.au (Rohan LENARD)
Date: 22 Feb 95 21:08:08 GMT Raw View
In article <3i9l38$ds7@erinews.ericsson.se>,
Jonas Nygren <ehsjony@ehs.ericsson.se> wrote:
>
>This is a small example compiled with Sun C++ (fairly recent version), problem
>or not - you judge:
>
[..snip..]
>> CC q.cc
>"q.cc", line 4: Error: Cannot have a return type of int* for A<int>::operator->().
>"q.cc", line 8: Where: While specializing A<int>.
>"q.cc", line 8: Where: Specialized in non-template code.
>1 Error(s) detected.
This is a compiler problem. I'd complain to your vendor...
Regards,
Rohan
--
----------------------------------------------------------------------------
rjl@iassf.easams.com.au | All quotes can be attributed to my automated quote
Rohan Lenard | writing tool. Yours for just $19.95; and if you
+61-2-367-4555 | call now you'll get a free set of steak knives ...
Author: sp106@york.ac.uk ("stephen")
Date: 24 Feb 1995 14:05:03 GMT Raw View
Nathan Myers (ncm@netcom.com) wrote:
: >Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
: >>The STL documentation and source code that I have are from Sept/Oct '95,
: >>so the problem may have been addressed. Given that iterators in STL have
: >>pointer like semantics, why is there no operator-> defined for them?
: >>This came to light recently after I implemented an STL-like container and
: >>someone came to me saying that they had loads of code like
: >> (*iter).member()
: The operator -> is not part of the required interface for iterators
: because that would place an extra burden on writers of iterators.
: We can all expect to write hundreds of iterators in our careers, and
: you would soon resent being obliged to provide such an unnecessary
: operator.
Surely the point is more simple than this: that given an operator->
the iterator would unable to work on a container containing simple
objects. I ran into this when writing my own STL'ish library, a
iterator for Container<int> _may_ try to instantiate operator-> for
the iterator which will cause a compile time error. What is the
thinking on this at the moment, does the instantiation of the
operator _have_ to occur, and if not does the syntax of the code
that would be generated if this was the case have to be correct?
If not then template code of any type is an error waiting to happen.
stephen
--
####################################################
# sp106@york.ac.uk # http://www.york.ac.uk/~sp106 #
# Each set includes a turntable, nine inch icing #
# bag, six high definition nozzles... #
####################################################
Author: ehsjony@ehs.ericsson.se (Jonas Nygren)
Date: 20 Feb 1995 08:49:44 GMT Raw View
In article 793019747snz@wslint.demon.co.uk, kevlin@wslint.demon.co.uk (Kevlin Henney) writes:
> In article <3hvufr$qkd@erinews.ericsson.se>
> ehsjony@ehs.ericsson.se "Jonas Nygren" writes:
>
> >Some compilers generate ALL functions for a template, not only the ones used.
> >In such a case you would get a problem with having an iterator<int> together
> >with the overloaded op->. Can op-> have been left out for this reason?
>
> There isn't a problem w/ that, as far as I can tell. Since you cannot use
This is a small example compiled with Sun C++ (fairly recent version), problem
or not - you judge:
> cat q.cc
template<class T> struct A {
T *p;
T *operator->() { return p; }
};
main() {
A<int> a;
return 0;
}
> CC q.cc
"q.cc", line 4: Error: Cannot have a return type of int* for A<int>::operator->().
"q.cc", line 8: Where: While specializing A<int>.
"q.cc", line 8: Where: Specialized in non-template code.
1 Error(s) detected.
>
> the x->m syntax w/ an int 'pointer', there is no way you could use this
> function legally in this 'sugared' form.
>
> Consider the new class auto_ptr<> - which I presume has operator-> - and
> works w/ all types.
>
> +---------------------------+------------------------------------+
> | Kevlin A P Henney | Money confers neither intelligence |
> | kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
> | Westinghouse Systems Ltd | |
> +---------------------------+------------------------------------+
Author: ehsjony@ehs.ericsson.se (Jonas Nygren)
Date: 16 Feb 1995 16:28:43 GMT Raw View
In article 792839123snz@wslint.demon.co.uk, kevlin@wslint.demon.co.uk (Kevlin Henney) writes:
> In article <D40MHL.E77@research.att.com>
> ark@research.att.com "Andrew Koenig" writes:
>
> >The real trouble, which I don't think has been mentioned before
> >in this thread, is that iterators are generally constrained in
> >what one can do with them. In particular, if p is an iterator,
> >one can copy from *p or copy to *p, but one cannot generally mutate
> >*p in place unless p is a forward iterator (remembering that
> >bidirectional and random access iterators are forward iterators).
> >
> >Since most algorithms use input or output iterators rather than
> >forward iterator, allowing p->m whenever (*p).m is allowed would
> >be less useful than one might think because (*p).m is legal in
> >fewer places than one might think.
>
> Yes, perhaps I should qualify this - I've been generally talking
> about forward iterators w/o stating that explicitly (my fault). But,
> given that something like a random access iterator supports the syntax
> sugaring of a[i] for *(a + i), I would expect op-> to be possible. I
> believe that BS even states this in C++ Programming Language (2e) - ie.
> if you provide op* and op[], for politeness op-> ought to be included.
Some compilers generate ALL functions for a template, not only the ones used.
In such a case you would get a problem with having an iterator<int> together
with the overloaded op->. Can op-> have been left out for this reason?
>
> +---------------------------+------------------------------------+
> | Kevlin A P Henney | Money confers neither intelligence |
> | kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
> | Westinghouse Systems Ltd | |
> +---------------------------+------------------------------------+
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Fri, 17 Feb 1995 11:15:47 +0000 Raw View
In article <3hvufr$qkd@erinews.ericsson.se>
ehsjony@ehs.ericsson.se "Jonas Nygren" writes:
>Some compilers generate ALL functions for a template, not only the ones used.
>In such a case you would get a problem with having an iterator<int> together
>with the overloaded op->. Can op-> have been left out for this reason?
There isn't a problem w/ that, as far as I can tell. Since you cannot use
the x->m syntax w/ an int 'pointer', there is no way you could use this
function legally in this 'sugared' form.
Consider the new class auto_ptr<> - which I presume has operator-> - and
works w/ all types.
+---------------------------+------------------------------------+
| Kevlin A P Henney | Money confers neither intelligence |
| kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
| Westinghouse Systems Ltd | |
+---------------------------+------------------------------------+
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Tue, 14 Feb 1995 10:20:50 +0000 Raw View
In article <D3tF7q.JDG@undergrad.math.uwaterloo.ca>
rridge@calum.csclub.uwaterloo.ca "Ross Ridge" writes:
>Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
>>The STL documentation and source code that I have are from Sept/Oct '95,
>>so the problem may have been addressed. Given that iterators in STL have
>>pointer like semantics, why is there no operator-> defined for them?
>>
>>This came to light recently after I implemented an STL-like container and
>>someone came to me saying that they had loads of code like
>>
>> (*iter).member()
>
>The obvious reason is because the dot (.) operator may not be defined
>for (*iter). Consider when the iterator is for a container of
>integers.
This is so obvious that I think I accounted for this in the original posting.
If the requirement is expressed as
x->m is defined where (*x).m is legal
This continues to work for containers of int, because (*x).m is not legal
neither is x->m.
+---------------------------+------------------------------------+
| Kevlin A P Henney | Money confers neither intelligence |
| kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
| Westinghouse Systems Ltd | |
+---------------------------+------------------------------------+
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Tue, 14 Feb 1995 10:37:59 +0000 Raw View
In article <ncmD3yKH3.DxJ@netcom.com> ncm@netcom.com "Nathan Myers" writes:
>>Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
>>>The STL documentation and source code that I have are from Sept/Oct '95,
>>>so the problem may have been addressed. Given that iterators in STL have
>>>pointer like semantics, why is there no operator-> defined for them?
>>>
>>>This came to light recently after I implemented an STL-like container and
>>>someone came to me saying that they had loads of code like
>>>
>>> (*iter).member()
>
>The operator -> is not part of the required interface for iterators
>because that would place an extra burden on writers of iterators.
>We can all expect to write hundreds of iterators in our careers, and
>you would soon resent being obliged to provide such an unnecessary
>operator.
So speaks a library implementor :-) When I added operator-> to our iterators
it was a relief not a burden: code could be written in the manner to
which we had been accustomed, ie. nobody writes
(*ptr).member
Or if they do, you gently point out that the way most of the C/C++ community
normally writes this is
ptr->member
I expect to write hundreds of iterators in my career, and I expect every one
of them to have operator->. Not because of bloody mindedness, but because
it's standard! Users expect it and so vendors will provide it. It would be
unfortunate if the de facto standard did not realise that this is a hole
that will be filled one way or another.
As far as coding it goes, I have to admit that operator-> is the least
challenging operator of the lot! Adding one line functions to make life
easier will not give you RSI ;-)
>Early drafts had operators + and - on forward iterators, but they
>were removed for the same reason.
Why weren't templatised + and - operators provided then? Given that such a
save-your-typing-fingers philosophy was applied to 4 of the 6 relational
operators. Are we interested in how easy these libraries are to use or
how easy they are to implement? I'm afraid that the library implementor
ought to come second, otherwise there is a misrepresentation of concerns.
Clearly, if it's impossible or very hard then this is a consideration, but
that is clearly not the case here.
>The requirements on iterators are
>deliberately *minimal*; the use of iterators is necessarily rather
>stylized, therefore, restricted to exactly those expressions listed in
>the iterator requirements.
One of the most abused quotes in computer science wrt simplicity is
Einsteins' "make it as simple as possible but no simpler". It appears that
this is unnecessarily simple.
>Because the list is so small, you have no trouble memorizing what you
>can and can't do with an iterator. That list will never change.
>This is a feature.
It's memorising what you _can't_ do that causes the problems ;-)
+---------------------------+------------------------------------+
| Kevlin A P Henney | Money confers neither intelligence |
| kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
| Westinghouse Systems Ltd | |
+---------------------------+------------------------------------+
Author: ark@research.att.com (Andrew Koenig)
Date: Wed, 15 Feb 1995 00:24:57 GMT Raw View
In article <792757250snz@wslint.demon.co.uk> Kevlin@wslint.demon.co.uk writes:
> This is so obvious that I think I accounted for this in the original posting.
> If the requirement is expressed as
> x->m is defined where (*x).m is legal
> This continues to work for containers of int, because (*x).m is not legal
> neither is x->m.
The real trouble, which I don't think has been mentioned before
in this thread, is that iterators are generally constrained in
what one can do with them. In particular, if p is an iterator,
one can copy from *p or copy to *p, but one cannot generally mutate
*p in place unless p is a forward iterator (remembering that
bidirectional and random access iterators are forward iterators).
Since most algorithms use input or output iterators rather than
forward iterator, allowing p->m whenever (*p).m is allowed would
be less useful than one might think because (*p).m is legal in
fewer places than one might think.
--
--Andrew Koenig
ark@research.att.com
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Wed, 15 Feb 1995 09:05:23 +0000 Raw View
In article <D40MHL.E77@research.att.com>
ark@research.att.com "Andrew Koenig" writes:
>The real trouble, which I don't think has been mentioned before
>in this thread, is that iterators are generally constrained in
>what one can do with them. In particular, if p is an iterator,
>one can copy from *p or copy to *p, but one cannot generally mutate
>*p in place unless p is a forward iterator (remembering that
>bidirectional and random access iterators are forward iterators).
>
>Since most algorithms use input or output iterators rather than
>forward iterator, allowing p->m whenever (*p).m is allowed would
>be less useful than one might think because (*p).m is legal in
>fewer places than one might think.
Yes, perhaps I should qualify this - I've been generally talking
about forward iterators w/o stating that explicitly (my fault). But,
given that something like a random access iterator supports the syntax
sugaring of a[i] for *(a + i), I would expect op-> to be possible. I
believe that BS even states this in C++ Programming Language (2e) - ie.
if you provide op* and op[], for politeness op-> ought to be included.
+---------------------------+------------------------------------+
| Kevlin A P Henney | Money confers neither intelligence |
| kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
| Westinghouse Systems Ltd | |
+---------------------------+------------------------------------+
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Wed, 8 Feb 1995 13:08:13 +0000 Raw View
The STL documentation and source code that I have are from Sept/Oct '95,
so the problem may have been addressed. Given that iterators in STL have
pointer like semantics, why is there no operator-> defined for them?
This came to light recently after I implemented an STL-like container and
someone came to me saying that they had loads of code like
(*iter).member()
which most people would expect to be written as
iter->member()
There is no problem for types w/o members, since code for operator-> in
an iterator will compile, but it will not be usable by clients except as
operator->().
Can anyone shed any light? Otherwise this is something to suggest to the
committee.
+---------------------------+------------------------------------+
| Kevlin A P Henney | Money confers neither intelligence |
| kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
| Westinghouse Systems Ltd | |
+---------------------------+------------------------------------+
Author: u865151@student.canberra.edu.au (Burger / John Adriaan (ISE))
Date: Thu, 9 Feb 95 08:21:25 GMT Raw View
In article <792248893snz@wslint.demon.co.uk>,
Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
>This came to light recently after I implemented an STL-like container and
>someone came to me saying that they had loads of code like
>
> (*iter).member()
>
>which most people would expect to be written as
>
> iter->member()
>
>There is no problem for types w/o members, since code for operator-> in
>an iterator will compile, but it will not be usable by clients except as
>operator->().
I understood the problem with operator ->() was that it only "looked"
right for AutoPointer-type classes, those where you used the object
itself as a pointer (maybe for auto-deletion). With the above, if iter is
declared as:
Iter *iter // (say),
then *iter is the object that has the operator ->(), not iter, which is
merely a pointer, in which case a -> dereferences that pointer. So it would
look like (*iter)->member(), which "looks" strange.
John "Or did you just say that?" Burger
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Thu, 9 Feb 1995 09:06:48 +0000 Raw View
In article <792248893snz@wslint.demon.co.uk>
Kevlin@wslint.demon.co.uk "Kevlin Henney" writes:
>The STL documentation and source code that I have are from Sept/Oct '95,
^^^
Wow, that's pretty impressive! Perhaps I meant '94... but you never know ;-)
+---------------------------+------------------------------------+
| Kevlin A P Henney | Money confers neither intelligence |
| kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
| Westinghouse Systems Ltd | |
+---------------------------+------------------------------------+
Author: Nat Pryce <np2@doc.ic.ac.uk>
Date: 9 Feb 1995 14:05:36 GMT Raw View
kevlin@wslint.demon.co.uk (Kevlin Henney) wrote:
> The STL documentation and source code that I have are from Sept/Oct '95,
> so the problem may have been addressed. Given that iterators in STL have
> pointer like semantics, why is there no operator-> defined for them?
<snip snip>
> Can anyone shed any light? Otherwise this is something to suggest to the
> committee.
I'd like to see this. However, what would happen if the contained
object was itself a pointer to an object? You couldn't have:
iter->->member
Or can you?
Anyway, couldn't you define a template function to expand the ->
operator into (*inter) in the same way as STL's != operator.
Ie, something along the lines of...
template<class T>
T &operator -> (iterator<T>)
{
return (*iterator);
}
Author: b91926@fsgm01.fnal.gov (David Sachs)
Date: 9 Feb 1995 11:16:20 -0600 Raw View
Nat Pryce <np2@doc.ic.ac.uk> writes:
>kevlin@wslint.demon.co.uk (Kevlin Henney) wrote:
>> The STL documentation and source code that I have are from Sept/Oct '95,
>> so the problem may have been addressed. Given that iterators in STL have
>> pointer like semantics, why is there no operator-> defined for them?
> <snip snip>
>> Can anyone shed any light? Otherwise this is something to suggest to the
>> committee.
>I'd like to see this. However, what would happen if the contained
>object was itself a pointer to an object? You couldn't have:
> iter->->member
>Or can you?
>Anyway, couldn't you define a template function to expand the ->
>operator into (*inter) in the same way as STL's != operator.
>Ie, something along the lines of...
>template<class T>
>T &operator -> (iterator<T>)
>{
> return (*iterator);
>}
Actually operator->() must be a member function with no arguments, so
it would have to be added to the (template) class definitions and
look something like this:
T* operator->() { return &**this; }
or an equivalent form which includes the code from operator*().
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Fri, 10 Feb 1995 15:29:57 +0000 Raw View
In article <3hd7fg$p1a@frigate.doc.ic.ac.uk> np2@doc.ic.ac.uk "Nat Pryce" writes:
>kevlin@wslint.demon.co.uk (Kevlin Henney) wrote:
>> The STL documentation and source code that I have are from Sept/Oct '95,
>> so the problem may have been addressed. Given that iterators in STL have
>> pointer like semantics, why is there no operator-> defined for them?
> <snip snip>
>> Can anyone shed any light? Otherwise this is something to suggest to the
>> committee.
>
>I'd like to see this. However, what would happen if the contained
>object was itself a pointer to an object? You couldn't have:
> iter->->member
>
>Or can you?
Overloading operators does not change the syntax of the language, so
you will get a compilation error. It is not meaningful to use the class
member access operator (in sugared form) without accessing a class member.
+---------------------------+------------------------------------+
| Kevlin A P Henney | Money confers neither intelligence |
| kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
| Westinghouse Systems Ltd | |
+---------------------------+------------------------------------+
Author: kevlin@wslint.demon.co.uk (Kevlin Henney)
Date: Fri, 10 Feb 1995 15:27:35 +0000 Raw View
In article <1995Feb9.082125.12137@csc.canberra.edu.au>
u865151@student.canberra.edu.au "Burger / John Adriaan (ISE" writes:
[...]
>I understood the problem with operator ->() was that it only "looked"
>right for AutoPointer-type classes, those where you used the object
>itself as a pointer (maybe for auto-deletion). With the above, if iter is
>declared as:
>Iter *iter // (say),
>then *iter is the object that has the operator ->(), not iter, which is
>merely a pointer, in which case a -> dereferences that pointer. So it would
>look like (*iter)->member(), which "looks" strange.
I'm not quite sure what you're saying here, given that
thing **pp;
(*pp)->member;
is the 'pointer as iterator' equivalent. Does this look strange? The point
is that iterators are conceptually pointers (why else would they have
op*, relational operations and inc/dec operations defined for them?),
and therefore your quoted example looks quite acceptable.
Compare this to the original posting which questioned how pointer-like
iterators actually were if you had to keep writing
(*iter).member
instead of
iter->member
[BTW this assumes a standard decl for an iterator as a value rather than
a pointer]
Most self respecting C/C++ programmers would wonder why the -> hadn't been
used given that it is taken as read to be =valent to (*)., correct their
code, get a compile error, and then be left scratching their heads at this
astonishing oversight!
+---------------------------+------------------------------------+
| Kevlin A P Henney | Money confers neither intelligence |
| kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
| Westinghouse Systems Ltd | |
+---------------------------+------------------------------------+
Author: rridge@calum.csclub.uwaterloo.ca (Ross Ridge)
Date: Sat, 11 Feb 1995 03:04:38 GMT Raw View
Kevlin Henney <Kevlin@wslint.demon.co.uk> wrote:
>The STL documentation and source code that I have are from Sept/Oct '95,
>so the problem may have been addressed. Given that iterators in STL have
>pointer like semantics, why is there no operator-> defined for them?
>
>This came to light recently after I implemented an STL-like container and
>someone came to me saying that they had loads of code like
>
> (*iter).member()
The obvious reason is because the dot (.) operator may not be defined
for (*iter). Consider when the iterator is for a container of
integers.
Ross Ridge
>which most people would expect to be written as
>
> iter->member()
>
>There is no problem for types w/o members, since code for operator-> in
>an iterator will compile, but it will not be usable by clients except as
>operator->().
>
>Can anyone shed any light? Otherwise this is something to suggest to the
>committee.
>
>+---------------------------+------------------------------------+
>| Kevlin A P Henney | Money confers neither intelligence |
>| kevlin@wslint.demon.co.uk | nor wisdom on those who spend it |
>| Westinghouse Systems Ltd | |
>+---------------------------+------------------------------------+
--
l/ // Ross Ridge -- The Great HTMU, Ook +1 519 883 4329
[oo][oo] rridge@csclub.uwaterloo.ca http://csclub.uwaterloo.ca/u/rridge/
-()-/()/
db //